rm(list = ls())

library(leaflet)
library(maps)
library(rgdal)
library(DT)
library(ggplot2)
library(ggthemes)
library(plotly)
library(magrittr)
library(readxl)
library(plyr)
library(dplyr)
library(tidyr)
library(readr)
library(stringi)
library(RColorBrewer)
library(countrycode)
require(gridExtra)
## IMPORT DATA General ACA information
aca_general_raw <- read_excel("Data/states_aca_general.xlsx", sheet = 2, col_names = FALSE)
# States health outcomes
health_ind_raw <- read_excel("Data/states_health_ind.xlsx", sheet = 4, col_names = FALSE)
# Insurance coverage data Long format
insurance_long <- read_excel("Data/insurance-clean.xlsx", sheet = 1, col_names = TRUE)
# Wide format
insurance <- read_excel("Data/insurance-clean.xlsx", sheet = 2, col_names = TRUE)
# Demographic information
demographics1 <- read.csv("Data/Population_Age_Income.csv", header = TRUE)
# Provided with Assignment 4 (want the yearly population data)
demographics2 <- read_excel("Data/PopulationEstimates.xls")
# Election Results
election <- read_excel("Data/US_Presidential_Results_by_State_1828-2016.xlsx", 
    sheet = 2, col_names = FALSE)
## CLEAN DATA List of states abbreviations
state_abbreviations <- c("AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", 
    "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", 
    "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", 
    "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", 
    "VA", "WA", "WV", "WI", "WY")
## CLEAN INSURANCE RATES DATA (WIDE) Drop unnecessary columns
insurance <- insurance[1:50, -1]
# Rename variables
colnames(insurance) <- c("state_abb", "state", "uninsured_num_2008", "uninsured_pct_2008", 
    "uninsured_num_2009", "uninsured_pct_2009", "uninsured_num_2010", "uninsured_pct_2010", 
    "uninsured_num_2011", "uninsured_pct_2011", "uninsured_num_2012", "uninsured_pct_2012", 
    "uninsured_num_2013", "uninsured_pct_2013", "uninsured_num_2014", "uninsured_pct_2014", 
    "uninsured_num_2015", "uninsured_pct_2015")
# Create variables for insurance rates
insurance$insured_pct_2008 <- 100 - insurance$uninsured_pct_2008
insurance$insured_pct_2009 <- 100 - insurance$uninsured_pct_2009
insurance$insured_pct_2010 <- 100 - insurance$uninsured_pct_2010
insurance$insured_pct_2011 <- 100 - insurance$uninsured_pct_2011
insurance$insured_pct_2012 <- 100 - insurance$uninsured_pct_2012
insurance$insured_pct_2013 <- 100 - insurance$uninsured_pct_2013
insurance$insured_pct_2014 <- 100 - insurance$uninsured_pct_2014
insurance$insured_pct_2015 <- 100 - insurance$uninsured_pct_2015
# Reorder variables
insurance <- insurance[, c("state_abb", "state", "uninsured_num_2008", "uninsured_pct_2008", 
    "insured_pct_2008", "uninsured_num_2009", "uninsured_pct_2009", "insured_pct_2009", 
    "uninsured_num_2010", "uninsured_pct_2010", "insured_pct_2010", "uninsured_num_2011", 
    "uninsured_pct_2011", "insured_pct_2011", "uninsured_num_2012", "uninsured_pct_2012", 
    "insured_pct_2012", "uninsured_num_2013", "uninsured_pct_2013", "insured_pct_2013", 
    "uninsured_num_2014", "uninsured_pct_2014", "insured_pct_2014", "uninsured_num_2015", 
    "uninsured_pct_2015", "insured_pct_2015")]
## CLEAN INSURANCE RATES DATA (LONG) Rename variables
colnames(insurance_long) <- c("year", "state", "population", "uninsured_num", 
    "uninsured_pct", "insured_num", "insured_pct")
# Add state abbreviations First create a look-up table (based on wide data)
state_abb_lookup <- insurance[, c("state", "state_abb")]
# Then do the matching
insurance_long$state_abb <- state_abb_lookup$state_abb[match(insurance_long$state, 
    state_abb_lookup$state)]
# Reorder variable
insurance_long <- insurance_long[, c(1:2, ncol(insurance_long), 3:(ncol(insurance_long) - 
    1))]
# Order observations (by state, then by year)
insurance_long <- insurance_long[order(insurance_long$state, insurance_long$year), 
    ]
## CLEAN ACA GENERAL DATA Keep only relevant rows and columns
aca_general <- aca_general_raw[6:57, 1:73]
# Label variables for ACA general data
names(aca_general) <- c("state", "unins_all_pct_10", "unins_all_pct_15", "unins_all_decr_pct", 
    "unins_all_decr", "cov_emp", "cov_parents_plan", "lifetime_lim_preACA_tot", 
    "lifetime_lim_preACA_child", "lifetime_lim_preACA_adultM", "lifetime_lim_preACA_adultF", 
    "cov_private_tot", "cov_private_child", "cov_private_adultM", "cov_private_adultF", 
    "premium_emp_avg_growth_pct_00to10", "premium_emp_avg_growth_pct_10to15", 
    "premium_emp_savings_15", "premium_emp_savings_16", "MLR_rebate_beneficiaries_12", 
    "MLR_rebate_amt_12", "MLR_rebate_beneficiaries_13", "MLR_rebate_amt_13", 
    "MLR_rebate_beneficiaries_14", "MLR_rebate_amt_14", "MLR_rebate_beneficiaries_15", 
    "MLR_rebate_amt_15", "MLR_rebate_amt_12to15", "medicaid_enroll_13", "medicaid_enroll_16", 
    "medicaid_enroll_child_13", "medicaid_enroll_incr_13to16", "medicaid_full_duals", 
    "medicaid_partial_duals", "medicaid_full_or_partial_duals", "state_has_expanded", 
    "insurance_incr_medicaid", "cholest_scr_incr_medicaid", "mammogram_incr_medicaid", 
    "papsmear_incr_medicaid", "clinic_care_incr_medicaid", "all_care_incr_medicaid", 
    "phycisian_visit_ann_incr_medicaid", "depression_decr_medicaid", "good_health_incr_medicaid", 
    "deaths_ann_decr_medicaid", "catastrophic_oop_ann_decr_medicaid", "indebted_ppl_decr_medicaid", 
    "fed_spending_net_incr_inMil", "uncompensated_care_decr_inMil", "mental_substance_elig_medicaid_share", 
    "mental_substance_elig_medicaid", "preexisting_condition_09", "cov_mkt_plan_16", 
    "cov_mkt_16", "receive_tax_credit", "avg_tax_credit", "receive_cost_sharing", 
    "avg_num_mkt_plans_avail_17", "cov_mkt_under75D_pct", "cov_mkt_under100D_pct", 
    "cov_offmkt_elig_tax_credit", "rate_review_funds_to_state", "HIECP_grant_award_to_state", 
    "medicare_enroll_16", "medicare_benef_donuthole", "medicare_benef_donuthole_savings_tot", 
    "medicare_benef_donuthole_savings_avg", "medicare_partB_free_prev_services", 
    "medicare_partB_free_prev_services_share", "medicare_incr_readmit_rate", 
    "medicare_avoided_readmit", "accountable_care_org_num")
# Trim white space on state variable
aca_general$state <- stri_trim_both(aca_general$state)
# Change format of variables Apart from T/F variable for 'state has
# expanded'
aca_general$state_has_expanded[aca_general$state_has_expanded == "yes"] <- TRUE
aca_general$state_has_expanded[aca_general$state_has_expanded == "no"] <- FALSE
# Convert others to numeric form
for (j in c(2:35, 37:73)) {
    aca_general[[j]] <- as.numeric(aca_general[[j]])
}
# Save USA data separately
aca_general_USA <- aca_general[aca_general$state == "United States", ]
# Drop USA and DC data
aca_general <- aca_general[!(aca_general$state %in% c("United States", "District of Columbia")), 
    ]
# Add state abbreviations
aca_general$state_abb <- state_abbreviations
aca_general <- aca_general[, c(1, ncol(aca_general), 2:(ncol(aca_general) - 
    1))]
# Drop raw data
rm(aca_general_raw)
## CLEAN HEALTH INDICATOR DATA Keep only relevant rows and columns
health_ind <- health_ind_raw[4:6703, c(1, 3:6)]
# Label variables
names(health_ind) <- c("state", "measure", "year", "rate", "rank")
# Simplify date (years) - only keep last year if range was given
health_ind$year[health_ind$year == "07/2009 - 06/2012"] <- "2012"
health_ind$year[health_ind$year == "07/2010 - 06/2013"] <- "2013"
health_ind$year[health_ind$year == "07/2012 - 06/2015"] <- "2015"
health_ind$year[health_ind$year == "10/2013-9/2014"] <- "2014"
health_ind$year[health_ind$year == "2008-09"] <- "2009"
health_ind$year[health_ind$year == "2010-11"] <- "2011"
health_ind$year[health_ind$year == "2011-12"] <- "2012"
health_ind$year[health_ind$year == "2011/12"] <- "2012"
health_ind$year[health_ind$year == "2012-13"] <- "2013"
health_ind$year[health_ind$year == "2013-14"] <- "2014"
health_ind$year[health_ind$year == "2013(Q2-Q4)"] <- "2013"
health_ind$year[health_ind$year == "2014-15"] <- "2015"
health_ind$year[health_ind$year == "2015(Q2-Q4)"] <- "2015"
# Export to excel to manually label variable names
unique_measures <- unique(as.factor(health_ind$measure))
# Copied in from excel sheet
unique_measures_relabelled <- c("a.summary_access", "a.unins_adult", "a.unins_child", 
    "a.no_care_bc_cost_adult", "a.high_OOP_relative_under65", "a.at_risk_no_routine_doc_adult", 
    "a.no_dental_adult", "q.summary_prev_treat", "q.with_usual_care_adult", 
    "q.with_cancer_screening_adult", "q.with_vaccines_adult", "q.with_medical_home_child", 
    "q.with_prev_medical_dental_child", "q.with_mental_healthcare_child", "q.with_vaccines_infant", 
    "q.drug_should_avoid_medicare", "q.drug_should_avoid_3conditions_medicare", 
    "q.good_health_provider_medicare", "q.mortality_4conditions_medicare", "q.CLABSI_infection_ratio", 
    "q.info_recovery_hospitalized", "q.good_hospital_staff_hospitalized", "q.improve_mobility_homehealth", 
    "q.improved_wounds_homehealth", "q.sores_NHres", "q.antipsychotic_med_NHres", 
    "u.summary_avoidable_hosp_cost", "u.hosp_asthma_child", "u.hosp_ambulatory_65to74yrs", 
    "u.hosp_ambulatory_above75yrs", "u.30day_hosp_readmit_medicare", "u.30day_hosp_readmit_NHres", 
    "u.hosp_6mos_NHres", "u.hosp_medicare_homehealth", "u.avoidable_ER_medicare", 
    "u.tot_reimb_employer_ins", "u.tot_reimb_medicare", "h.summary_healthy_lives", 
    "h.deaths_amenable", "h.yrs_lost_potential_life_before75", "h.deaths_breast_cancer_F", 
    "h.deaths_colorectal_cancer", "h.deaths_suicide", "h.deaths_infant_mortality", 
    "h.poor_health_adult", "h.smoke_adult", "h.obese_adult", "h.obese_child", 
    "h.poor_dental_adult", "u.premium_emp_private", "u.premium_emp_private_unadj", 
    "u.reimb_medicare_unadj", "u.deaths_amenable_black", "u.deaths_amenable_white", 
    NA, "q.with_prev_screening_above50yrs", NA)
# Replace variable names with abbreviated version
for (i in 1:57) {
    health_ind$measure <- replace(health_ind$measure, health_ind$measure == 
        unique_measures[i], unique_measures_relabelled[i])
}
# Remove the NA's
health_ind <- health_ind[!is.na(health_ind$measure), ]
# Remove duplicates By state, measure.year
health_ind <- health_ind[!duplicated(health_ind[, 1:3]), ]
# Interact measure and year
health_ind$measure_year <- interaction(health_ind$measure, health_ind$year)
# Convert to character variable
health_ind$measure_year <- as.character(health_ind$measure_year)
# Pre-reshape: Store existing data as 'long'
health_ind_long <- health_ind
# Reshape wide
health_ind <- as.data.frame(cbind(health_ind$state, health_ind$measure_year, 
    health_ind$rate))
# Drop rank data for now
names(health_ind) <- c("state", "measure_year", "rate")
health_ind <- reshape(health_ind, idvar = "state", timevar = "measure_year", 
    direction = "wide")
# Drop 'rate' from the name
names(health_ind)[2:ncol(health_ind)] <- substr(names(health_ind), 6, nchar(names(health_ind)))[2:ncol(health_ind)]
# Drop variables who have all entries as NA Due to 'unbalanced panel' in
# reshaping First create a vector to record if variable is all NA
variable_all_NA <- vector(mode = "logical", length = ncol(health_ind))
for (j in 1:ncol(health_ind)) {
    if (sum(is.na(health_ind[[j]])) == 52) {
        variable_all_NA[j] <- TRUE
    }
}
# Only keep the variables that are NOT all NA
health_ind <- health_ind[, !variable_all_NA]
# Change format of variables To character variable
health_ind$state <- as.character(health_ind$state)
# To numeric variable
for (j in c(2:164)) {
    health_ind[[j]] <- as.character(health_ind[[j]])
    health_ind[[j]] <- as.numeric(health_ind[[j]])
}
# Save USA data separately
health_ind_USA <- health_ind[health_ind$state == "United States", ]
# Drop USA and DC data
health_ind <- health_ind[!(health_ind$state %in% c("United States", "District of Columbia")), 
    ]
# Label state abbreviations
health_ind$state_abb <- state_abbreviations
health_ind <- health_ind[, c(1, ncol(health_ind), 2:(ncol(health_ind) - 1))]
# Drop raw data
rm(health_ind_raw)
## CLEAN DEMOGRAPHIC (1) DATA Drop unnecessary row and column
demographics1 <- demographics1[-1, -1]
# Rename variables
colnames(demographics1) <- c("state", "income", "population", "ppl_age0to4", 
    "ppl_age5to9", "ppl_age10to14", "ppl_age15to19", "ppl_age20to24", "ppl_age25to29", 
    "ppl_age30to34", "ppl_age35to39", "ppl_age40to44", "ppl_age45to49", "ppl_age50to54", 
    "ppl_age55to59", "ppl_age60to64", "ppl_age65to69", "ppl_age70to74", "ppl_age75to79", 
    "ppl_age80to84", "ppl_age85plus")
# Drop observations DC and PR
demographics1 <- demographics1[!demographics1$state == "District of Columbia" & 
    !demographics1$state == "Puerto Rico", ]
# Label state abbreviations
demographics1$state_abb <- state_abbreviations
demographics1 <- demographics1[, c(1, ncol(demographics1), 2:(ncol(demographics1) - 
    1))]
# Change format of variables To character variable
demographics1$state <- as.character(demographics1$state)
# To numeric variable
for (j in c(3:ncol(demographics1))) {
    demographics1[[j]] <- as.character(demographics1[[j]])
    demographics1[[j]] <- as.numeric(demographics1[[j]])
}
# BEA regions
demographics1$BEA_region <- ""
demographics1$BEA_region[demographics1$state_abb %in% c("ME", "NH", "VT", "MA", 
    "CT", "RI")] <- "New England"
demographics1$BEA_region[demographics1$state_abb %in% c("NY", "NJ", "PA", "MD", 
    "DE")] <- "Mideast"
demographics1$BEA_region[demographics1$state_abb %in% c("WI", "IL", "MI", "IN", 
    "OH")] <- "Great Lakes"
demographics1$BEA_region[demographics1$state_abb %in% c("WV", "KY", "VA", "TN", 
    "NC", "SC", "AR", "LA", "MS", "AL", "GA", "FL")] <- "Southeast"
demographics1$BEA_region[demographics1$state_abb %in% c("ND", "SD", "NE", "KS", 
    "MN", "IA", "MO")] <- "Plains"
demographics1$BEA_region[demographics1$state_abb %in% c("MT", "ID", "WY", "UT", 
    "CO")] <- "Rocky Mountains"
demographics1$BEA_region[demographics1$state_abb %in% c("AZ", "NM", "TX", "OK")] <- "Southwest"
demographics1$BEA_region[demographics1$state_abb %in% c("WA", "OR", "CA", "NV", 
    "AK", "HI")] <- "Far West"
# Tag income level (category)
demographics1$income_level <- ""
demographics1$income_level[demographics1$income >= 60000] <- "High"
demographics1$income_level[demographics1$income >= 50000 & demographics1$income < 
    60000] <- "Upper Middle"
demographics1$income_level[demographics1$income >= 45000 & demographics1$income < 
    50000] <- "Lower Middle"
demographics1$income_level[demographics1$income < 45000] <- "Low"
# Convert to factor variable
demographics1$income_level <- factor(demographics1$income_level, levels = c("Low", 
    "Lower Middle", "Upper Middle", "High"))
## CLEAN DEMOGRAPHIC (2) DATA
colnames(demographics2) <- demographics2[2, ]
# Drop first few rows (non-observations)
demographics2 <- demographics2[-(1:2), ]
# Drop county-level data, keep state-level data only
demographics2 <- demographics2[demographics2$Area_Name == "United States" | 
    demographics2$State != lag(demographics2$State), ]
# Keep only columns of population from 2010 to 2015
demographics2 <- demographics2[, c("State", "Area_Name", "POP_ESTIMATE_2010", 
    "POP_ESTIMATE_2011", "POP_ESTIMATE_2012", "POP_ESTIMATE_2013", "POP_ESTIMATE_2014", 
    "POP_ESTIMATE_2015")]
# Change format of variables To character variable
for (j in c(3:8)) {
    demographics2[[j]] <- as.numeric(demographics2[[j]])
}
# Rename variables
colnames(demographics2) <- c("state_abb", "state", "population_2010", "population_2011", 
    "population_2012", "population_2013", "population_2014", "population_2015")
## CLEAN ELECTION DATA Keep only 2012 and 2008 data, and data for the 50
## states
election <- election[4:53, c("X0", "X5", "X6", "X9", "X10")]
# Rename variables
colnames(election) <- c("state", "Dem_pct_2012", "Rep_pct_2012", "Dem_pct_2008", 
    "Rep_pct_2008")
# Add state abbreviations Match with look-up table
election$state_abb <- state_abb_lookup$state_abb[match(election$state, state_abb_lookup$state)]
# Change format of variables To numeric variable
for (j in c(4:6)) {
    election[[j]] <- as.numeric(election[[j]])
}
# Calculate winning party for each state
election$party_2012 <- ifelse(election$Dem_pct_2012 > election$Rep_pct_2012, 
    "Democratic", "Republican")
election$party_2008 <- ifelse(election$Dem_pct_2008 > election$Rep_pct_2008, 
    "Democratic", "Republican")
# Reorder variables
election <- election[, c("state", "state_abb", "Dem_pct_2012", "Rep_pct_2012", 
    "party_2012", "Dem_pct_2008", "Rep_pct_2008", "party_2008")]
## EXPORT DATASETS FOR SHINY USE
#write_csv(insurance, "/Users/gracekongyx/Documents/*6_Data Science/QMSS G4063 Data Visualization/Final Project/Data/shiny_insurance.csv")

(1) Health Insurance Coverage

## SOME DATA PREPARATION Look-up information into insurance and
## insurance_long, on: Party (2012)
insurance_long$party_2012 <- election$party_2012[match(insurance_long$state, 
    election$state)]
insurance$party_2012 <- election$party_2012[match(insurance$state, election$state)]
# BEA region
insurance_long$BEA_region <- demographics1$BEA_region[match(insurance_long$state, 
    demographics1$state)]
insurance$BEA_region <- demographics1$BEA_region[match(insurance$state, demographics1$state)]
# Income level
insurance_long$income_level <- demographics1$income_level[match(insurance_long$state, 
    demographics1$state)]
insurance$income_level <- demographics1$income_level[match(insurance$state, 
    demographics1$state)]
# Also find nation-wide trend for insurance
insurance_long_US <- data.frame(year = c(2008, 2009, 2010, 2011, 2012, 2013, 
    2014, 2015), uninsured_pct = c(16.8, 17.5, 18.2, 17.2, 16.9, 16.6, 13.3, 
    10.5))

The following figure displays the trend in the uninsured rate between 2008 and 2015. Results are shown for the USA average (in black), as well as for every individual state (in color). The states are grouped and color-coded by region to facilitate identification, where one can toggle the display to show a particular region to locate a particular state. We see a clear downward trend in the uninsured rate once most of the Affordable Care Act (ACA) provisions were implemented in 2014.

## PLOT 1
plot1 <- (ggplot(insurance_long, aes(year, uninsured_pct)) + geom_line(aes(color = BEA_region, 
    group = state, label = uninsured_num)) + scale_x_continuous(breaks = c(2008, 
    2009, 2010, 2011, 2012, 2013, 2014, 2015)) + scale_y_continuous(breaks = c(5, 
    10, 15, 20, 25, 30)) + labs(x = "Year", y = "% Uninsured", color = "Region") + 
    geom_line(data = insurance_long_US, lwd = 0.8) + geom_vline(xintercept = 2010, 
    linetype = 2, color = "gray30") + geom_vline(xintercept = 2014, linetype = 2, 
    color = "gray30") + annotate("text", x = 2009.4, y = 25, label = "Obama \nsigns ACA", 
    color = "black", fontface = 2, size = 3) + annotate("text", x = 2013.4, 
    y = 24.5, label = "Most ACA \nprovisions \ntake effect", color = "black", 
    fontface = 2, size = 3) + annotate("text", x = 2014.2, y = 11, label = "USA \nAverage", 
    color = "black", fontface = 2, size = 3) + ggtitle("Change in Percentage Uninsured by State, \nfrom 2008 to 2015") + 
    theme_minimal() + theme(plot.title = element_text(face = "bold", hjust = 0, 
    size = 12)))
ggplotly(plot1, dynamicTicks = FALSE, tooltip = c("state", "year", "uninsured_pct", 
    "uninsured_num"))

In the following plot, I explore the difference between Democratic and Republican states, based on the 2012 US Presidential Election results. It is clear that the democratic states largely have a lower uninsured rate than the Republican states, though both groups experienced declines in the uninsured rates in 2014.

## PLOT 2
plot2 <- (ggplot(insurance_long, aes(year, uninsured_pct)) + geom_line(aes(color = party_2012, 
    group = state, label = uninsured_num)) + scale_x_continuous(breaks = c(2008, 
    2009, 2010, 2011, 2012, 2013, 2014, 2015)) + scale_y_continuous(breaks = c(5, 
    10, 15, 20, 25, 30)) + scale_color_manual(values = c("steel blue", "firebrick1")) + 
    labs(x = "Year", y = "% Uninsured", color = "Party \n(2012 Winner)") + geom_line(data = insurance_long_US, 
    lwd = 1) + geom_vline(xintercept = 2010, linetype = 2, color = "gray30") + 
    geom_vline(xintercept = 2014, linetype = 2, color = "gray30") + annotate("text", 
    x = 2009.4, y = 25, label = "Obama \nsigns ACA", color = "black", fontface = 2, 
    size = 3) + annotate("text", x = 2013.4, y = 24.5, label = "Most ACA \nprovisions \ntake effect", 
    color = "black", fontface = 2, size = 3) + annotate("text", x = 2014.2, 
    y = 11, label = "USA \nAverage", color = "black", fontface = 2, size = 3) + 
    ggtitle("Change in Percentage Uninsured by Party, \nfrom 2008 to 2015") + 
    theme_minimal() + theme(plot.title = element_text(face = "bold", hjust = 0, 
    size = 12)))
ggplotly(plot2, dynamicTicks = FALSE, tooltip = c("state", "year", "uninsured_pct", 
    "uninsured_num"))
## PLOT 3 Subset relevant variables
insurance_2015 <- insurance[, c("state", "uninsured_pct_2015", "insured_pct_2015", 
    "party_2012", "BEA_region", "income_level")]
# Boxplots by party
plot3a <- (ggplot(insurance_2015, aes(x = reorder(party_2012, insured_pct_2015), 
    y = insured_pct_2015)) + geom_boxplot(aes(fill = party_2012, label = insured_pct_2015), 
    color = "gray30") + coord_flip() + scale_fill_manual(values = c("steel blue", 
    "firebrick")) + ggtitle("Democratic vs. Republican States") + theme_minimal() + 
    theme(plot.title = element_text(face = "bold", hjust = 0.37, size = 12), 
        legend.position = "none", axis.title.x = element_blank(), axis.title.y = element_blank()))
# Boxplots by BEA region
plot3b <- (ggplot(insurance_2015, aes(x = reorder(BEA_region, insured_pct_2015), 
    y = insured_pct_2015)) + geom_boxplot(aes(fill = BEA_region, label = insured_pct_2015), 
    color = "gray30") + coord_flip() + scale_fill_manual(values = brewer.pal(n = 8, 
    name = "Dark2")) + ggtitle("By Bureau of Economic Analysis (BEA) Region") + 
    theme_minimal() + theme(plot.title = element_text(face = "bold", hjust = 0.24, 
    size = 12), legend.position = "none", axis.title.x = element_blank(), axis.title.y = element_blank()))
# Boxplots by income level
plot3c <- (ggplot(insurance_2015, aes(x = income_level, y = insured_pct_2015)) + 
    geom_boxplot(aes(fill = income_level, label = insured_pct_2015), color = "gray30") + 
    coord_flip() + scale_fill_manual(values = brewer.pal(n = 4, name = "Dark2")) + 
    labs(x = "", y = "% Insured (2015)") + ggtitle("By State's Income Level") + 
    theme_minimal() + theme(plot.title = element_text(face = "bold", hjust = 0.39, 
    size = 12), legend.position = "none", axis.title.y = element_blank()))
# Combine plots vertically
grid.arrange(plot3a, plot3b, plot3c, nrow = 3, top = "2015 Insurance Rates at a Glance")

## SOME DATA RESHAPING Reshape aca_general (long), keeping the interesting
## quantities Import uninsured number (2015)
aca_general$unins_all_15 <- insurance$uninsured_num_2015[match(aca_general$state, 
    insurance$state)]
# Keep only select variables
aca_general_long <- aca_general[, c("state", "state_abb", "cov_emp", "cov_mkt_plan_16", 
    "medicaid_enroll_16", "medicare_enroll_16", "unins_all_15")]
# The actual reshaping
aca_general_long <- reshape(aca_general_long, varying = c("cov_emp", "cov_mkt_plan_16", 
    "medicaid_enroll_16", "medicare_enroll_16", "unins_all_15"), v.names = "Number", 
    timevar = "Source", times = c("Employer", "Marketplace", "Medicaid / CHIP", 
        "Medicare", "Uninsured"), new.row.names = 1:1000, direction = "long")
# Look-up information into aca_general_long, on: Party (2012)
aca_general_long$party_2012 <- election$party_2012[match(aca_general_long$state, 
    election$state)]
# BEA region
aca_general_long$BEA_region <- demographics1$BEA_region[match(aca_general_long$state, 
    demographics1$state)]
# Income level
aca_general_long$income_level <- demographics1$income_level[match(aca_general_long$state, 
    demographics1$state)]
# Population
aca_general_long$population_2015 <- demographics2$population_2015[match(aca_general_long$state, 
    demographics2$state)]
# Calculate percentage from number and population
aca_general_long$percentage <- aca_general_long$Number/aca_general_long$population_2015 * 
    100

Next, I investigate the main health insurance and coverage sources, namely employer coverage, the individual marketplace, Medicaid / Childrens’ Health Insurance Program (CHIP), and Medicare for the aged. I broke down the results by party and income level, taking a simple (unweighted) average across the states in the categories. We observe that employer coverage rates increase as income level increases, especially for Democratic states. Democratic and low income states have more people on Medicaid / CHIP than Republican and low income states.

## PLOT 4
aca_general_long_by_party_income <- ddply(aca_general_long, c("party_2012", 
    "income_level", "Source"), summarise, avg_pct = mean(percentage))
plot4 <- (ggplot(aca_general_long_by_party_income, aes(income_level, avg_pct, 
    fill = Source)) + geom_col(position = "dodge") + facet_grid(party_2012 ~ 
    .) + labs(x = "Income Level", y = "Average % in State", color = "Source of \nInsurance") + 
    scale_fill_manual(values = brewer.pal(n = 6, name = "Dark2")[c(1:3, 6, 4)]) + 
    ggtitle("Sources of Health Insurance, \nby Party and Income Level") + theme_minimal() + 
    theme(plot.title = element_text(face = "bold", hjust = 0, size = 12)))
ggplotly(plot4, tooltip = c("income_level", "Source", "avg_pct"))
## PREPARATION FOR FURTHER PLOTS (INCLUDING DATA TABLE) Want to combine
## information on insurance coverage with key information on health
## outcomes/access and affordability
key_indicators <- state_abb_lookup
## Merge in information to the data table on the following Demographic
## Information Income level
key_indicators$income_level <- demographics1$income_level[match(key_indicators$state_abb, 
    demographics1$state_abb)]
# Insurance Coverage Percentage insured (2015)
key_indicators$insured_pct_2015 <- insurance$insured_pct_2015[match(key_indicators$state_abb, 
    insurance$state_abb)]
# Percentage insured (2014)
key_indicators$insured_pct_2014 <- insurance$insured_pct_2014[match(key_indicators$state_abb, 
    insurance$state_abb)]
# Indicator: Whether state has expanded medicare
key_indicators$state_has_expanded <- aca_general$state_has_expanded[match(key_indicators$state_abb, 
    aca_general$state_abb)]
# Health outcomes and access Mortality amenable to health care, deaths per
# 10000 population
key_indicators$deaths_amenable_2014 <- health_ind$h.deaths_amenable.2014[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Years of Potential Life Lost before 75
key_indicators$years_life_lost <- health_ind$h.yrs_lost_potential_life_before75.2014[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Adults with a usual source of care (%)
key_indicators$usual_care_2015 <- health_ind$q.with_usual_care_adult.2015[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Adults with age/gender-appropriate cancer screenings (%)
key_indicators$with_cancer_screening <- health_ind$q.with_cancer_screening_adult.2014[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Adults with age-appropriate vaccines (%)
key_indicators$with_vaccines <- health_ind$q.with_vaccines_adult.2015[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Affordability and cost-efficiency Individuals under age 65 with high OOP
# medical costs relative to annual household income
key_indicators$high_OOP_relative <- health_ind$a.high_OOP_relative_under65.2015[match(key_indicators$state_abb, 
    health_ind$state_abb)]
# Average annual growth in family premiums for employer coverage (between
# 2010 and 2015)
key_indicators$premium_ann_growth_10_15 <- aca_general$premium_emp_avg_growth_pct_10to15[match(key_indicators$state_abb, 
    aca_general$state_abb)]
# Marketplace consumers who could select a plan for less than $100
key_indicators$IM_plan_under_100 <- aca_general$cov_mkt_under100D_pct[match(key_indicators$state_abb, 
    aca_general$state_abb)]
# Net increase in federal spending (millions)
key_indicators$incr_fed_spending_mil <- aca_general$fed_spending_net_incr_inMil[match(key_indicators$state_abb, 
    aca_general$state_abb)]

(2) Health Outcomes and Access

## PLOT 5
plot5 <- (ggplot(key_indicators, aes(insured_pct_2014, deaths_amenable_2014, 
    color = income_level, shape = state_has_expanded)) + geom_point(size = 2) + 
    geom_smooth(aes(group = income_level), method = "lm", lwd = 1, se = FALSE) + 
    labs(x = "% Insured", y = "Deaths Preventable by Healthcare Intervention \n(per 100,000 People)", 
        color = "Income \nLevel", shape = "State has \nExpanded \nMedicaid") + 
    scale_color_manual(values = brewer.pal(n = 4, name = "Dark2")) + ggtitle("Relationship Between Avoidable Mortality and \nHealth Insurance Coverage Among States") + 
    theme_minimal() + theme(plot.title = element_text(face = "bold", hjust = 0.5, 
    size = 12)))
plot5

## DATA PROCESSING Obtain shape files of US states
map_states = map("state", fill = TRUE, plot = FALSE)
# Standardize name format with rest of assignment Function to conver to
# proper case
properCase <- function(x) {
    s <- strsplit(x, " ")[[1]]
    paste(toupper(substring(s, 1, 1)), substring(s, 2), sep = "", collapse = " ")
}
# Convert to proper case
map_states$state <- sapply(map_states$names, properCase)
# Rename the main component of states with multiple parts in the map
map_states$state[map_states$state == "Massachusetts:main"] <- "Massachusetts"
map_states$state[map_states$state == "Michigan:south"] <- "Michigan"
map_states$state[map_states$state == "New York:main"] <- "New York"
map_states$state[map_states$state == "North Carolina:main"] <- "North Carolina"
map_states$state[map_states$state == "Virginia:main"] <- "Virginia"
map_states$state[map_states$state == "Washington:main"] <- "Washington"
# Match with state abbreviations
map_states$state_abb <- state_abb_lookup$state_abb[match(map_states$state, state_abb_lookup$state)]
# Then strip off all the extra location information for states with multiple
# parts (leaving just the state name)
for (i in 1:length(map_states$state)) {
    map_states$state[i] <- unlist(strsplit(map_states$state[i], ":"))[1]
}
# Get coordinates of state centers
states_centers <- state.center
state.center <- cbind(states_centers, state_abb_lookup)
# Health outcomes: Import key indicators data, matched by state Remember to
# later match information based on state, not state abbreviation (due to how
# we labelled above)
map_states$deaths_amenable_2014 <- key_indicators$deaths_amenable_2014[match(map_states$state, 
    key_indicators$state)]
map_states$usual_care_2015 <- key_indicators$usual_care_2015[match(map_states$state, 
    key_indicators$state)]
map_states$with_cancer_screening <- key_indicators$with_cancer_screening[match(map_states$state, 
    key_indicators$state)]
map_states$with_vaccines <- key_indicators$with_vaccines[match(map_states$state, 
    key_indicators$state)]
# Cost outcomes: Import key indicators data, matched by state Remember to
# later match information based on state, not state abbreviation (due to how
# we labelled above)
map_states$high_OOP_relative <- key_indicators$high_OOP_relative[match(map_states$state, 
    key_indicators$state)]
map_states$premium_ann_growth_10_15 <- key_indicators$premium_ann_growth_10_15[match(map_states$state, 
    key_indicators$state)]
map_states$IM_plan_under_100 <- key_indicators$IM_plan_under_100[match(map_states$state, 
    key_indicators$state)]
map_states$incr_fed_spending_mil <- key_indicators$incr_fed_spending_mil[match(map_states$state, 
    key_indicators$state)]
## PLOT 6: LEAFLET MAP - HEALTH OUTCOMES
(leaflet(map_states) %>% setView(lat = 39.8282, lng = -96, zoom = 4) %>% addPolygons(color = "#333333", 
    weight = 1, smoothFactor = 0.5, fillOpacity = 0) %>% addPolygons(group = "Preventable Deaths", 
    fillColor = ~colorQuantile("RdYlGn", -deaths_amenable_2014)(-deaths_amenable_2014), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Preventable Mortality</b>", "<br/>", 
        "<b>per 100,000: </b>", map_states$deaths_amenable_2014)) %>% addPolygons(group = "Access to Usual Care", 
    fillColor = ~colorQuantile("RdYlGn", usual_care_2015)(usual_care_2015), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Access to Usual</b>", "<br/>", "<b>Source of Care: </b>", 
        map_states$usual_care_2015, "%")) %>% addPolygons(group = "Cancer Screenings Rate", 
    fillColor = ~colorQuantile("RdYlGn", with_cancer_screening)(with_cancer_screening), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Cancer Screenings</b>", "<br/>", "<b>Rate: </b>", 
        map_states$with_cancer_screening, "%")) %>% addPolygons(group = "Adult Vaccination Rate", 
    fillColor = ~colorQuantile("RdYlGn", with_vaccines)(with_vaccines), smoothFactor = 0.5, 
    stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", map_states$state, 
        "<br/>", "<b>Vaccination</b>", "<br/>", "<b>Rate: </b>", map_states$with_vaccines, 
        "%")) %>% addLabelOnlyMarkers(data = filter(state.center, state_abb != 
    "AK" & state_abb != "HI"), lng = ~x, lat = ~y, label = ~state_abb, labelOptions = labelOptions(noHide = T, 
    direction = "top", textOnly = T)) %>% addLayersControl(baseGroups = c("Preventable Deaths", 
    "Access to Usual Care", "Cancer Screenings Rate", "Adult Vaccination Rate"), 
    options = layersControlOptions(collapsed = FALSE)))

(3) Affordability and Cost Outcomes

## PLOT 7: LEAFLET MAP - AFFORDABILITY / COST OUTCOMES
(leaflet(map_states) %>% setView(lat = 39.8282, lng = -96, zoom = 4) %>% addPolygons(color = "#333333", 
    weight = 1, smoothFactor = 0.5, fillOpacity = 0) %>% addPolygons(group = "Contained OOP Costs", 
    fillColor = ~colorQuantile("RdYlGn", -high_OOP_relative)(-high_OOP_relative), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>High OOP Relative</b>", "<br/>", "<b>to Income: </b>", 
        map_states$high_OOP_relative, "%")) %>% addPolygons(group = "Premium Growth Rate", 
    fillColor = ~colorQuantile("RdYlGn", -premium_ann_growth_10_15)(-premium_ann_growth_10_15), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Annual Premium</b>", "<br/>", "<b>Growth Rate: </b>", 
        map_states$premium_ann_growth_10_15, "%")) %>% addPolygons(group = "Affordable Individual Marketplace Plan", 
    fillColor = ~colorQuantile("RdYlGn", IM_plan_under_100)(IM_plan_under_100), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Marketplace Consumers</b>", "<br/>", 
        "<b>Who Can Select Plan</b>", "<br/>", "<b>Under $100: </b>", map_states$IM_plan_under_100 * 
            100, "%")) %>% addPolygons(group = "Increase in Federal Spending", 
    fillColor = ~colorQuantile("RdYlGn", -incr_fed_spending_mil)(-incr_fed_spending_mil), 
    smoothFactor = 0.5, stroke = FALSE, fillOpacity = 0.6, popup = paste("<b>State: </b>", 
        map_states$state, "<br/>", "<b>Net Increase in Federal</b>", "<br/>", 
        "<b>Spending</b>: $", map_states$incr_fed_spending_mil, "million")) %>% 
    addLabelOnlyMarkers(data = filter(state.center, state_abb != "AK" & state_abb != 
        "HI"), lng = ~x, lat = ~y, label = ~state_abb, labelOptions = labelOptions(noHide = T, 
        direction = "top", textOnly = T)) %>% addLayersControl(baseGroups = c("Contained OOP Costs", 
    "Premium Growth Rate", "Affordable Individual Marketplace Plan", "Increase in Federal Spending"), 
    options = layersControlOptions(collapsed = FALSE)))

(4) Summary of States’ Performance

# Create data table reporting values
data_table_values <- key_indicators[ , c("state", "insured_pct_2015", "deaths_amenable_2014", "usual_care_2015", "high_OOP_relative", "premium_ann_growth_10_15")]
# Create data table reporting rank
data_table_rank <- data_table_values
# Convert each function to rank
  # Rank 1 is always more favorable (regardless of definition of variable)    
data_table_rank$r_insured_pct_2015 <- rank(-data_table_values$insured_pct_2015, na.last = "keep", ties.method = "min")
data_table_rank$r_deaths_amenable_2014 <- rank(data_table_values$deaths_amenable_2014, na.last = "keep", ties.method = "min")
data_table_rank$r_usual_care_2015 <- rank(-data_table_values$usual_care_2015, na.last = "keep", ties.method = "min")
data_table_rank$r_high_OOP_relative <- rank(data_table_values$high_OOP_relative, na.last = "keep", ties.method = "min")
data_table_rank$r_premium_ann_growth_10_15 <- rank(data_table_values$premium_ann_growth_10_15, na.last = "keep", ties.method = "min")
  # Remove value variables
data_table_rank$insured_pct_2015 <- NULL
data_table_rank$deaths_amenable_2014 <- NULL
data_table_rank$usual_care_2015 <- NULL
data_table_rank$high_OOP_relative <- NULL
data_table_rank$premium_ann_growth_10_15 <- NULL

The following data table presents the rankings of the states on the following insurance coverage, health and affordability outcomes: 1) Percentage of population insured 2) Deaths preventable by healthcare intervention (per 100,000 people) 3) Proportion of adults with access to a usual source of care 4) Proportion of people with high out-of-pocket costs (relative to household income) 5) Annual rate of health insurance premium growth from 2010 to 2015 A rank of 1 always indicates the more favorable outcome (i.e. higher insurance and treatment access rate, lower preventable mortality, OOP costs and premium growth)

## PLOT 8: DATA TABLE RANKING THE STATES ON VARIOUS MEASURES
datatable(data_table_rank, rownames = FALSE, colnames = c("State", "Percentage Insured", 
    "Fewer Preventable Deaths", "Usual Care Access", "OOP Contained", "Lower Annual Premium Growth"), 
    caption = "Rank of the 50 States in Insurance Coverage and Health Outcomes")

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

library(tm)
library(tm.plugin.lexisnexis)
library(readxl)
library(gtools)  # for smartbind
library(dplyr)   # for data_frame
library(lubridate)   # for date formatting
library(stringr)  
library(tools)  # Title case
library(quanteda)
library(ggplot2)

# Combine CSV and HTML Files
data <- read_excel("LexisNexis/NYTimes_Metadata.xlsx")
colnames(data) <- tolower(colnames(data))

# Correct data
data$date <- substr(parse_date_time(data$date, c("mdy")),1,10)
data$author <- toTitleCase(tolower(data$byline))
data$byline <- NULL

## Get Text files
source1 <- LexisNexisSource("LexisNexis/The_New_York1.html")
source2 <- LexisNexisSource("LexisNexis/The_New_York2.html")

corpus1 <- Corpus(source1, readerControl = list(language = NA))
corpus2 <- Corpus(source2, readerControl = list(language = NA))

corpus <- c(corpus1, corpus2)

# Convert to quanteda corpus
corpus <- quanteda::corpus(corpus)

## Add Metadata
# Check: match(data$headline, corpus$documents$heading)
corpus$documents$datetimestamp <- substring(corpus$documents$datetimestamp, 1,4)
corpus$documents$date <- corpus$documents$datetimestamp
corpus$documents$description <- corpus$documents$id

# options(width = 200)
# kwic(corpus, "Trump")
# 
save(corpus, file="nytimes.rda")

the Nummber of articles mentions Affordable care by years

dat <- data.frame(date =corpus$documents$datetimestamp, levels=c(1:1000))
ggplot(data=dat, aes(x=date))+geom_bar(stat="count")+ggtitle("Number of articles mentioned ACA by years")+theme_tufte()+ylab("Number of articles") + xlab("year")

load("nytimes.rda")
dfmtotal <- dfm(corpus, remove = stopwords("english"), stem = TRUE, removePunct = TRUE, removeNumbers = TRUE, tolower = TRUE, verbose = TRUE)
Creating a dfm from a corpus ...
   ... lowercasing
   ... tokenizing
   ... found 1,000 documents, 22,386 features
   ... removed 169 features, from 174 supplied (glob) feature types
   ... stemming features (English), trimmed 7834 feature variants
   ... created a 1,000 x 14,383 sparse dfm
   ... complete. 
Elapsed time: 2.81 seconds.
dfmtotal[, 1:5]
Document-feature matrix of: 1,000 documents, 5 features (88.9% sparse).
head(stopwords("english"), 20)
 [1] "i"          "me"         "my"         "myself"     "we"         "our"        "ours"       "ourselves" 
 [9] "you"        "your"       "yours"      "yourself"   "yourselves" "he"         "him"        "his"       
[17] "himself"    "she"        "her"        "hers"      
freq<-topfeatures(dfmtotal, 20)
library(ggplot2)  
wf <- data.frame(word=names(freq), freq=freq)   
p <- ggplot(subset(wf, freq>50), aes(word, freq))    
p <- p + geom_bar(stat="identity")
p <- p + geom_text(aes(label=freq), vjust=-0.2)+ scale_x_discrete(limits= wf$word)   
p <- p + theme(axis.text.x=element_text(angle=45, hjust=1))+ggtitle("Word frequency from 2011-2017")+theme_tufte()+ylab("Frequency of Stem") + xlab("Top 30 Used Stem")
p

library(quanteda)
library(stringr)
load('nytimes.rda')
library(tm)
NYT_source <- VectorSource(corpus$documents[,1])
NYT <- VCorpus(NYT_source)
documents <- corpus$documents
library(qdap)
removeNumPunct <- function(x){gsub("[^[:alpha:][:space:]]*", "", x)}
clean_corpus <- function(corpus){
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, content_transformer(tolower))
corpus <- tm_map(corpus, content_transformer(replace_symbol))
corpus <- tm_map(corpus, removeWords, c(stopwords("en"), "will", "can", "Paul
Krugman", "David Brooks", "Thomas L. Friedman", "Maureen Dowd", "Nicholas
Kristof"))
# We could add more stop words as above
corpus <- tm_map(corpus, stripWhitespace)
corpus <- tm_map(corpus, removeNumbers)
corpus <- tm_map(corpus, content_transformer(removeNumPunct))
return(corpus)
}
library(SnowballC)
NYT_clean <- clean_corpus(NYT)
NYT_stem <- tm_map(NYT_clean, stemDocument)
meta(NYT_stem, type = "local", tag = "author") <- documents$author
NYT_dtm <- DocumentTermMatrix(NYT_stem)
NYT_tdm <- TermDocumentMatrix(NYT_stem)
library(dplyr)
library(tidytext)
NYT_tdm2 <- tidy(NYT_tdm)
NYT_dtm2 <- tidy(NYT_dtm)
NYT_tidy <- tidy(NYT_stem)
NYT_tdm2 <- merge(NYT_tdm2, NYT_tidy, by.x = "document", by.y = "id", all.x =
TRUE)
NYT_dtm2 <- merge(NYT_dtm2, NYT_tidy, by.x = "document", by.y = "id", all.x =
TRUE)
library(wordcloud)
atxt <- documents$texts[documents$datetimestamp == "2011"]
btxt <- documents$texts[documents$datetimestamp == "2012"]
ctxt <- documents$texts[documents$datetimestamp == "2013"]
dtxt <- documents$texts[documents$datetimestamp == "2014"]
etxt <- documents$texts[documents$datetimestamp == "2015"]
ftxt <- documents$texts[documents$datetimestamp == "2016"]
gtxt <- documents$texts[documents$datetimestamp == "2017"]
clean.text <- function(x)
{
# tolower
x = tolower(x)
# remove rt
x = gsub("rt", "", x)
# remove at
x = gsub("@\\w+", "", x)
# remove punctuation
x = gsub("[[:punct:]]", "", x)
# remove numbers
x = gsub("[[:digit:]]", "", x)
# remove links http
x = gsub("http\\w+", "", x)
# remove tabs
x = gsub("[ |\t]{2,}", "", x)
# remove blank spaces at the beginning
x = gsub("^ ", "", x)
# remove blank spaces at the end
x = gsub(" $", "", x)
return(x)
}
aclean <- clean.text(atxt)
bclean <- clean.text(btxt)
cclean <- clean.text(ctxt)
dclean <- clean.text(dtxt)
eclean <- clean.text(etxt)
fclean <- clean.text(ftxt)
gclean <- clean.text(gtxt)
a <- paste(aclean, collapse=" ")
b <- paste(bclean, collapse=" ")
c <- paste(cclean, collapse=" ")
d <- paste(dclean, collapse=" ")
e <- paste(eclean, collapse=" ")
f <- paste(fclean, collapse=" ")
g <- paste(gclean, collapse=" ")
# put everything in a single vector
all <- c(a,b,c,d,e,f,g)
all <- removeWords(all, c("will", "can", "the", "that","are"))
# create corpus
corpus2 <- Corpus(VectorSource(all))
# create term-document matrix
cloudtdm <- TermDocumentMatrix(corpus2)
# convert as matrix
cloudtdm <- as.matrix(cloudtdm)
# add column names
colnames(cloudtdm) <- c("2011","2012","2013","2014","2015","2016","2017")
comparison.cloud(cloudtdm, random.order=FALSE,colors = brewer.pal(8, "Dark2"),title.size=1.5, max.words = 200)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IAogICAgZmlnX3dpZHRoOiAxMAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgoKYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCB0aWR5ID0gVFJVRX0Kcm0obGlzdD1scygpKQoKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KG1hcHMpCmxpYnJhcnkocmdkYWwpCmxpYnJhcnkoRFQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShwbG90bHkpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoc3RyaW5naSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoY291bnRyeWNvZGUpCnJlcXVpcmUoZ3JpZEV4dHJhKQpgYGAKCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBJTVBPUlQgREFUQQoKIyBHZW5lcmFsIEFDQSBpbmZvcm1hdGlvbgphY2FfZ2VuZXJhbF9yYXcgPC0gcmVhZF9leGNlbCgiRGF0YS9zdGF0ZXNfYWNhX2dlbmVyYWwueGxzeCIsIHNoZWV0PTIsIGNvbF9uYW1lcz1GQUxTRSkKCiMgU3RhdGVzIGhlYWx0aCBvdXRjb21lcwpoZWFsdGhfaW5kX3JhdyA8LSByZWFkX2V4Y2VsKCJEYXRhL3N0YXRlc19oZWFsdGhfaW5kLnhsc3giLCBzaGVldD00LCBjb2xfbmFtZXM9RkFMU0UpCgojIEluc3VyYW5jZSBjb3ZlcmFnZSBkYXRhCiAgIyBMb25nIGZvcm1hdAppbnN1cmFuY2VfbG9uZyA8LSByZWFkX2V4Y2VsKCJEYXRhL2luc3VyYW5jZS1jbGVhbi54bHN4Iiwgc2hlZXQ9MSwgY29sX25hbWVzPVRSVUUpCiAgIyBXaWRlIGZvcm1hdAppbnN1cmFuY2UgPC0gcmVhZF9leGNlbCgiRGF0YS9pbnN1cmFuY2UtY2xlYW4ueGxzeCIsIHNoZWV0PTIsIGNvbF9uYW1lcz1UUlVFKQoKIyBEZW1vZ3JhcGhpYyBpbmZvcm1hdGlvbgpkZW1vZ3JhcGhpY3MxIDwtIHJlYWQuY3N2KCJEYXRhL1BvcHVsYXRpb25fQWdlX0luY29tZS5jc3YiLCBoZWFkZXIgPSBUUlVFKQogICMgUHJvdmlkZWQgd2l0aCBBc3NpZ25tZW50IDQgKHdhbnQgdGhlIHllYXJseSBwb3B1bGF0aW9uIGRhdGEpCmRlbW9ncmFwaGljczIgPC0gcmVhZF9leGNlbCgiRGF0YS9Qb3B1bGF0aW9uRXN0aW1hdGVzLnhscyIpCgojIEVsZWN0aW9uIFJlc3VsdHMKZWxlY3Rpb24gPC0gcmVhZF9leGNlbCgiRGF0YS9VU19QcmVzaWRlbnRpYWxfUmVzdWx0c19ieV9TdGF0ZV8xODI4LTIwMTYueGxzeCIsIHNoZWV0PTIsIGNvbF9uYW1lcz1GQUxTRSkKYGBgCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBDTEVBTiBEQVRBCgojIExpc3Qgb2Ygc3RhdGVzIGFiYnJldmlhdGlvbnMKc3RhdGVfYWJicmV2aWF0aW9ucyA8LSBjKCJBTCIsICJBSyIsICJBWiIsICJBUiIsICJDQSIsICJDTyIsICJDVCIsICJERSIsICJGTCIsICJHQSIsICJISSIsICJJRCIsICJJTCIsICJJTiIsICJJQSIsICJLUyIsICJLWSIsICJMQSIsICJNRSIsICJNRCIsICJNQSIsICJNSSIsICJNTiIsICJNUyIsICJNTyIsICJNVCIsICJORSIsICJOViIsICJOSCIsICJOSiIsICJOTSIsICJOWSIsICJOQyIsICJORCIsICJPSCIsICJPSyIsICJPUiIsICJQQSIsICJSSSIsICJTQyIsICJTRCIsICJUTiIsICJUWCIsICJVVCIsICJWVCIsICJWQSIsICJXQSIsICJXViIsICJXSSIsICJXWSIpCgoKIyMgQ0xFQU4gSU5TVVJBTkNFIFJBVEVTIERBVEEgKFdJREUpCgojIERyb3AgdW5uZWNlc3NhcnkgY29sdW1ucwppbnN1cmFuY2UgPC0gaW5zdXJhbmNlWzE6NTAsIC0xXQoKIyBSZW5hbWUgdmFyaWFibGVzCmNvbG5hbWVzKGluc3VyYW5jZSkgPC0gYygic3RhdGVfYWJiIiwgInN0YXRlIiwgInVuaW5zdXJlZF9udW1fMjAwOCIsICJ1bmluc3VyZWRfcGN0XzIwMDgiLCAidW5pbnN1cmVkX251bV8yMDA5IiwgInVuaW5zdXJlZF9wY3RfMjAwOSIsICJ1bmluc3VyZWRfbnVtXzIwMTAiLCAidW5pbnN1cmVkX3BjdF8yMDEwIiwgInVuaW5zdXJlZF9udW1fMjAxMSIsICJ1bmluc3VyZWRfcGN0XzIwMTEiLCAidW5pbnN1cmVkX251bV8yMDEyIiwgInVuaW5zdXJlZF9wY3RfMjAxMiIsICJ1bmluc3VyZWRfbnVtXzIwMTMiLCAidW5pbnN1cmVkX3BjdF8yMDEzIiwgInVuaW5zdXJlZF9udW1fMjAxNCIsICJ1bmluc3VyZWRfcGN0XzIwMTQiLCAidW5pbnN1cmVkX251bV8yMDE1IiwgInVuaW5zdXJlZF9wY3RfMjAxNSIpCgojIENyZWF0ZSB2YXJpYWJsZXMgZm9yIGluc3VyYW5jZSByYXRlcwppbnN1cmFuY2UkaW5zdXJlZF9wY3RfMjAwOCA8LSAxMDAgLSBpbnN1cmFuY2UkdW5pbnN1cmVkX3BjdF8yMDA4Cmluc3VyYW5jZSRpbnN1cmVkX3BjdF8yMDA5IDwtIDEwMCAtIGluc3VyYW5jZSR1bmluc3VyZWRfcGN0XzIwMDkKaW5zdXJhbmNlJGluc3VyZWRfcGN0XzIwMTAgPC0gMTAwIC0gaW5zdXJhbmNlJHVuaW5zdXJlZF9wY3RfMjAxMAppbnN1cmFuY2UkaW5zdXJlZF9wY3RfMjAxMSA8LSAxMDAgLSBpbnN1cmFuY2UkdW5pbnN1cmVkX3BjdF8yMDExCmluc3VyYW5jZSRpbnN1cmVkX3BjdF8yMDEyIDwtIDEwMCAtIGluc3VyYW5jZSR1bmluc3VyZWRfcGN0XzIwMTIKaW5zdXJhbmNlJGluc3VyZWRfcGN0XzIwMTMgPC0gMTAwIC0gaW5zdXJhbmNlJHVuaW5zdXJlZF9wY3RfMjAxMwppbnN1cmFuY2UkaW5zdXJlZF9wY3RfMjAxNCA8LSAxMDAgLSBpbnN1cmFuY2UkdW5pbnN1cmVkX3BjdF8yMDE0Cmluc3VyYW5jZSRpbnN1cmVkX3BjdF8yMDE1IDwtIDEwMCAtIGluc3VyYW5jZSR1bmluc3VyZWRfcGN0XzIwMTUKCiMgUmVvcmRlciB2YXJpYWJsZXMKaW5zdXJhbmNlIDwtIGluc3VyYW5jZVsgLCBjKCJzdGF0ZV9hYmIiLCAic3RhdGUiLCAidW5pbnN1cmVkX251bV8yMDA4IiwgInVuaW5zdXJlZF9wY3RfMjAwOCIsICJpbnN1cmVkX3BjdF8yMDA4IiwgInVuaW5zdXJlZF9udW1fMjAwOSIsICJ1bmluc3VyZWRfcGN0XzIwMDkiLCAiaW5zdXJlZF9wY3RfMjAwOSIsICJ1bmluc3VyZWRfbnVtXzIwMTAiLCAidW5pbnN1cmVkX3BjdF8yMDEwIiwgImluc3VyZWRfcGN0XzIwMTAiLCAidW5pbnN1cmVkX251bV8yMDExIiwgInVuaW5zdXJlZF9wY3RfMjAxMSIsICJpbnN1cmVkX3BjdF8yMDExIiwgInVuaW5zdXJlZF9udW1fMjAxMiIsICJ1bmluc3VyZWRfcGN0XzIwMTIiLCAiaW5zdXJlZF9wY3RfMjAxMiIsICJ1bmluc3VyZWRfbnVtXzIwMTMiLCAidW5pbnN1cmVkX3BjdF8yMDEzIiwgImluc3VyZWRfcGN0XzIwMTMiLCAidW5pbnN1cmVkX251bV8yMDE0IiwgInVuaW5zdXJlZF9wY3RfMjAxNCIsICJpbnN1cmVkX3BjdF8yMDE0IiwgInVuaW5zdXJlZF9udW1fMjAxNSIsICJ1bmluc3VyZWRfcGN0XzIwMTUiLCAiaW5zdXJlZF9wY3RfMjAxNSIpXQoKCiMjIENMRUFOIElOU1VSQU5DRSBSQVRFUyBEQVRBIChMT05HKQoKIyBSZW5hbWUgdmFyaWFibGVzCmNvbG5hbWVzKGluc3VyYW5jZV9sb25nKSA8LSBjKCJ5ZWFyIiwgInN0YXRlIiwgInBvcHVsYXRpb24iLCAidW5pbnN1cmVkX251bSIsICJ1bmluc3VyZWRfcGN0IiwgImluc3VyZWRfbnVtIiwgImluc3VyZWRfcGN0IikKCiMgQWRkIHN0YXRlIGFiYnJldmlhdGlvbnMKICAjIEZpcnN0IGNyZWF0ZSBhIGxvb2stdXAgdGFibGUgKGJhc2VkIG9uIHdpZGUgZGF0YSkKc3RhdGVfYWJiX2xvb2t1cCA8LSBpbnN1cmFuY2VbICwgYygic3RhdGUiLCAic3RhdGVfYWJiIildCiAgIyBUaGVuIGRvIHRoZSBtYXRjaGluZwppbnN1cmFuY2VfbG9uZyRzdGF0ZV9hYmIgPC0gc3RhdGVfYWJiX2xvb2t1cCRzdGF0ZV9hYmJbbWF0Y2goaW5zdXJhbmNlX2xvbmckc3RhdGUsIHN0YXRlX2FiYl9sb29rdXAkc3RhdGUpXQogICMgUmVvcmRlciB2YXJpYWJsZQppbnN1cmFuY2VfbG9uZyA8LSBpbnN1cmFuY2VfbG9uZ1sgLCBjKDE6MiwgbmNvbChpbnN1cmFuY2VfbG9uZyksIDM6KG5jb2woaW5zdXJhbmNlX2xvbmcpLTEpKV0KCiMgT3JkZXIgb2JzZXJ2YXRpb25zIChieSBzdGF0ZSwgdGhlbiBieSB5ZWFyKQppbnN1cmFuY2VfbG9uZyA8LSBpbnN1cmFuY2VfbG9uZ1tvcmRlcihpbnN1cmFuY2VfbG9uZyRzdGF0ZSwgaW5zdXJhbmNlX2xvbmckeWVhciksIF0KCgojIyBDTEVBTiBBQ0EgR0VORVJBTCBEQVRBCgojIEtlZXAgb25seSByZWxldmFudCByb3dzIGFuZCBjb2x1bW5zCmFjYV9nZW5lcmFsIDwtIGFjYV9nZW5lcmFsX3Jhd1s2OjU3LCAxOjczXQoKIyBMYWJlbCB2YXJpYWJsZXMgZm9yIEFDQSBnZW5lcmFsIGRhdGEKbmFtZXMoYWNhX2dlbmVyYWwpIDwtIGMoInN0YXRlIiwgInVuaW5zX2FsbF9wY3RfMTAiLCAidW5pbnNfYWxsX3BjdF8xNSIsICJ1bmluc19hbGxfZGVjcl9wY3QiLCAidW5pbnNfYWxsX2RlY3IiLCAiY292X2VtcCIsICJjb3ZfcGFyZW50c19wbGFuIiwgImxpZmV0aW1lX2xpbV9wcmVBQ0FfdG90IiwgImxpZmV0aW1lX2xpbV9wcmVBQ0FfY2hpbGQiLCAibGlmZXRpbWVfbGltX3ByZUFDQV9hZHVsdE0iLCAibGlmZXRpbWVfbGltX3ByZUFDQV9hZHVsdEYiLCAiY292X3ByaXZhdGVfdG90IiwgImNvdl9wcml2YXRlX2NoaWxkIiwgImNvdl9wcml2YXRlX2FkdWx0TSIsICJjb3ZfcHJpdmF0ZV9hZHVsdEYiLCAicHJlbWl1bV9lbXBfYXZnX2dyb3d0aF9wY3RfMDB0bzEwIiwgInByZW1pdW1fZW1wX2F2Z19ncm93dGhfcGN0XzEwdG8xNSIsICJwcmVtaXVtX2VtcF9zYXZpbmdzXzE1IiwgInByZW1pdW1fZW1wX3NhdmluZ3NfMTYiLCAiTUxSX3JlYmF0ZV9iZW5lZmljaWFyaWVzXzEyIiwgIk1MUl9yZWJhdGVfYW10XzEyIiwgIk1MUl9yZWJhdGVfYmVuZWZpY2lhcmllc18xMyIsICJNTFJfcmViYXRlX2FtdF8xMyIsICJNTFJfcmViYXRlX2JlbmVmaWNpYXJpZXNfMTQiLCAiTUxSX3JlYmF0ZV9hbXRfMTQiLCAiTUxSX3JlYmF0ZV9iZW5lZmljaWFyaWVzXzE1IiwgIk1MUl9yZWJhdGVfYW10XzE1IiwgIk1MUl9yZWJhdGVfYW10XzEydG8xNSIsICJtZWRpY2FpZF9lbnJvbGxfMTMiLCAibWVkaWNhaWRfZW5yb2xsXzE2IiwgIm1lZGljYWlkX2Vucm9sbF9jaGlsZF8xMyIsICJtZWRpY2FpZF9lbnJvbGxfaW5jcl8xM3RvMTYiLCAibWVkaWNhaWRfZnVsbF9kdWFscyIsICJtZWRpY2FpZF9wYXJ0aWFsX2R1YWxzIiwgIm1lZGljYWlkX2Z1bGxfb3JfcGFydGlhbF9kdWFscyIsICJzdGF0ZV9oYXNfZXhwYW5kZWQiLCAiaW5zdXJhbmNlX2luY3JfbWVkaWNhaWQiLCAiY2hvbGVzdF9zY3JfaW5jcl9tZWRpY2FpZCIsICJtYW1tb2dyYW1faW5jcl9tZWRpY2FpZCIsICJwYXBzbWVhcl9pbmNyX21lZGljYWlkIiwgImNsaW5pY19jYXJlX2luY3JfbWVkaWNhaWQiLCAiYWxsX2NhcmVfaW5jcl9tZWRpY2FpZCIsICJwaHljaXNpYW5fdmlzaXRfYW5uX2luY3JfbWVkaWNhaWQiLCAiZGVwcmVzc2lvbl9kZWNyX21lZGljYWlkIiwgImdvb2RfaGVhbHRoX2luY3JfbWVkaWNhaWQiLCAiZGVhdGhzX2Fubl9kZWNyX21lZGljYWlkIiwgImNhdGFzdHJvcGhpY19vb3BfYW5uX2RlY3JfbWVkaWNhaWQiLCAiaW5kZWJ0ZWRfcHBsX2RlY3JfbWVkaWNhaWQiLCAiZmVkX3NwZW5kaW5nX25ldF9pbmNyX2luTWlsIiwgInVuY29tcGVuc2F0ZWRfY2FyZV9kZWNyX2luTWlsIiwgIm1lbnRhbF9zdWJzdGFuY2VfZWxpZ19tZWRpY2FpZF9zaGFyZSIsICJtZW50YWxfc3Vic3RhbmNlX2VsaWdfbWVkaWNhaWQiLCAicHJlZXhpc3RpbmdfY29uZGl0aW9uXzA5IiwgImNvdl9ta3RfcGxhbl8xNiIsICJjb3ZfbWt0XzE2IiwgInJlY2VpdmVfdGF4X2NyZWRpdCIsICJhdmdfdGF4X2NyZWRpdCIsICJyZWNlaXZlX2Nvc3Rfc2hhcmluZyIsICJhdmdfbnVtX21rdF9wbGFuc19hdmFpbF8xNyIsICJjb3ZfbWt0X3VuZGVyNzVEX3BjdCIsICJjb3ZfbWt0X3VuZGVyMTAwRF9wY3QiLCAiY292X29mZm1rdF9lbGlnX3RheF9jcmVkaXQiLCAicmF0ZV9yZXZpZXdfZnVuZHNfdG9fc3RhdGUiLCAiSElFQ1BfZ3JhbnRfYXdhcmRfdG9fc3RhdGUiLCAibWVkaWNhcmVfZW5yb2xsXzE2IiwgIm1lZGljYXJlX2JlbmVmX2RvbnV0aG9sZSIsICJtZWRpY2FyZV9iZW5lZl9kb251dGhvbGVfc2F2aW5nc190b3QiLCAibWVkaWNhcmVfYmVuZWZfZG9udXRob2xlX3NhdmluZ3NfYXZnIiwgIm1lZGljYXJlX3BhcnRCX2ZyZWVfcHJldl9zZXJ2aWNlcyIsICJtZWRpY2FyZV9wYXJ0Ql9mcmVlX3ByZXZfc2VydmljZXNfc2hhcmUiLCAibWVkaWNhcmVfaW5jcl9yZWFkbWl0X3JhdGUiLCAibWVkaWNhcmVfYXZvaWRlZF9yZWFkbWl0IiwgImFjY291bnRhYmxlX2NhcmVfb3JnX251bSIpCgojIFRyaW0gd2hpdGUgc3BhY2Ugb24gc3RhdGUgdmFyaWFibGUKYWNhX2dlbmVyYWwkc3RhdGUgPC0gc3RyaV90cmltX2JvdGgoYWNhX2dlbmVyYWwkc3RhdGUpCgojIENoYW5nZSBmb3JtYXQgb2YgdmFyaWFibGVzCiAgIyBBcGFydCBmcm9tIFQvRiB2YXJpYWJsZSBmb3IgInN0YXRlIGhhcyBleHBhbmRlZCIKYWNhX2dlbmVyYWwkc3RhdGVfaGFzX2V4cGFuZGVkW2FjYV9nZW5lcmFsJHN0YXRlX2hhc19leHBhbmRlZD09InllcyJdIDwtIFRSVUUgCmFjYV9nZW5lcmFsJHN0YXRlX2hhc19leHBhbmRlZFthY2FfZ2VuZXJhbCRzdGF0ZV9oYXNfZXhwYW5kZWQ9PSJubyJdIDwtIEZBTFNFIAogICMgQ29udmVydCBvdGhlcnMgdG8gbnVtZXJpYyBmb3JtCmZvciAoaiBpbiBjKDI6MzUsIDM3OjczKSkgewogIGFjYV9nZW5lcmFsW1tqXV0gPC0gYXMubnVtZXJpYyhhY2FfZ2VuZXJhbFtbal1dKQp9CgojIFNhdmUgVVNBIGRhdGEgc2VwYXJhdGVseQphY2FfZ2VuZXJhbF9VU0EgPC0gYWNhX2dlbmVyYWxbYWNhX2dlbmVyYWwkc3RhdGU9PSJVbml0ZWQgU3RhdGVzIiwgXQoKIyBEcm9wIFVTQSBhbmQgREMgZGF0YQphY2FfZ2VuZXJhbCA8LSBhY2FfZ2VuZXJhbFshKGFjYV9nZW5lcmFsJHN0YXRlICVpbiUgYygiVW5pdGVkIFN0YXRlcyIsICJEaXN0cmljdCBvZiBDb2x1bWJpYSIpKSwgXQoKIyBBZGQgc3RhdGUgYWJicmV2aWF0aW9ucwphY2FfZ2VuZXJhbCRzdGF0ZV9hYmIgPC0gc3RhdGVfYWJicmV2aWF0aW9ucwphY2FfZ2VuZXJhbCA8LSBhY2FfZ2VuZXJhbFsgLCBjKDEsIG5jb2woYWNhX2dlbmVyYWwpLCAyOihuY29sKGFjYV9nZW5lcmFsKS0xKSldCgojIERyb3AgcmF3IGRhdGEKcm0oYWNhX2dlbmVyYWxfcmF3KQoKCiMjIENMRUFOIEhFQUxUSCBJTkRJQ0FUT1IgREFUQQoKIyBLZWVwIG9ubHkgcmVsZXZhbnQgcm93cyBhbmQgY29sdW1ucwpoZWFsdGhfaW5kIDwtIGhlYWx0aF9pbmRfcmF3WzQ6NjcwMywgYygxLCAzOjYpXQoKIyBMYWJlbCB2YXJpYWJsZXMKbmFtZXMoaGVhbHRoX2luZCkgPC0gYygic3RhdGUiLCAibWVhc3VyZSIsICJ5ZWFyIiwgInJhdGUiLCAicmFuayIpCgojIFNpbXBsaWZ5IGRhdGUgKHllYXJzKSAtIG9ubHkga2VlcCBsYXN0IHllYXIgaWYgcmFuZ2Ugd2FzIGdpdmVuCmhlYWx0aF9pbmQkeWVhcltoZWFsdGhfaW5kJHllYXI9PSIwNy8yMDA5IC0gMDYvMjAxMiJdIDwtICIyMDEyIgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMDcvMjAxMCAtIDA2LzIwMTMiXSA8LSAiMjAxMyIKaGVhbHRoX2luZCR5ZWFyW2hlYWx0aF9pbmQkeWVhcj09IjA3LzIwMTIgLSAwNi8yMDE1Il0gPC0gIjIwMTUiCmhlYWx0aF9pbmQkeWVhcltoZWFsdGhfaW5kJHllYXI9PSIxMC8yMDEzLTkvMjAxNCJdIDwtICIyMDE0IgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAwOC0wOSJdIDwtICIyMDA5IgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMC0xMSJdIDwtICIyMDExIgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMS0xMiJdIDwtICIyMDEyIgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMS8xMiJdIDwtICIyMDEyIgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMi0xMyJdIDwtICIyMDEzIgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMy0xNCJdIDwtICIyMDE0IgpoZWFsdGhfaW5kJHllYXJbaGVhbHRoX2luZCR5ZWFyPT0iMjAxMyhRMi1RNCkiXSA8LSAiMjAxMyIKaGVhbHRoX2luZCR5ZWFyW2hlYWx0aF9pbmQkeWVhcj09IjIwMTQtMTUiXSA8LSAiMjAxNSIKaGVhbHRoX2luZCR5ZWFyW2hlYWx0aF9pbmQkeWVhcj09IjIwMTUoUTItUTQpIl0gPC0gIjIwMTUiCgojIEV4cG9ydCB0byBleGNlbCB0byBtYW51YWxseSBsYWJlbCB2YXJpYWJsZSBuYW1lcwp1bmlxdWVfbWVhc3VyZXMgPC0gdW5pcXVlKGFzLmZhY3RvcihoZWFsdGhfaW5kJG1lYXN1cmUpKQogICMgQ29waWVkIGluIGZyb20gZXhjZWwgc2hlZXQKdW5pcXVlX21lYXN1cmVzX3JlbGFiZWxsZWQgPC0gYygiYS5zdW1tYXJ5X2FjY2VzcyIsICJhLnVuaW5zX2FkdWx0IiwgImEudW5pbnNfY2hpbGQiLCAiYS5ub19jYXJlX2JjX2Nvc3RfYWR1bHQiLCAiYS5oaWdoX09PUF9yZWxhdGl2ZV91bmRlcjY1IiwgImEuYXRfcmlza19ub19yb3V0aW5lX2RvY19hZHVsdCIsICJhLm5vX2RlbnRhbF9hZHVsdCIsICJxLnN1bW1hcnlfcHJldl90cmVhdCIsICJxLndpdGhfdXN1YWxfY2FyZV9hZHVsdCIsICJxLndpdGhfY2FuY2VyX3NjcmVlbmluZ19hZHVsdCIsICJxLndpdGhfdmFjY2luZXNfYWR1bHQiLCAicS53aXRoX21lZGljYWxfaG9tZV9jaGlsZCIsICJxLndpdGhfcHJldl9tZWRpY2FsX2RlbnRhbF9jaGlsZCIsICJxLndpdGhfbWVudGFsX2hlYWx0aGNhcmVfY2hpbGQiLCAicS53aXRoX3ZhY2NpbmVzX2luZmFudCIsICJxLmRydWdfc2hvdWxkX2F2b2lkX21lZGljYXJlIiwgInEuZHJ1Z19zaG91bGRfYXZvaWRfM2NvbmRpdGlvbnNfbWVkaWNhcmUiLCAicS5nb29kX2hlYWx0aF9wcm92aWRlcl9tZWRpY2FyZSIsICJxLm1vcnRhbGl0eV80Y29uZGl0aW9uc19tZWRpY2FyZSIsICJxLkNMQUJTSV9pbmZlY3Rpb25fcmF0aW8iLCAicS5pbmZvX3JlY292ZXJ5X2hvc3BpdGFsaXplZCIsICJxLmdvb2RfaG9zcGl0YWxfc3RhZmZfaG9zcGl0YWxpemVkIiwgInEuaW1wcm92ZV9tb2JpbGl0eV9ob21laGVhbHRoIiwgInEuaW1wcm92ZWRfd291bmRzX2hvbWVoZWFsdGgiLCAicS5zb3Jlc19OSHJlcyIsICJxLmFudGlwc3ljaG90aWNfbWVkX05IcmVzIiwgInUuc3VtbWFyeV9hdm9pZGFibGVfaG9zcF9jb3N0IiwgInUuaG9zcF9hc3RobWFfY2hpbGQiLCAidS5ob3NwX2FtYnVsYXRvcnlfNjV0bzc0eXJzIiwgInUuaG9zcF9hbWJ1bGF0b3J5X2Fib3ZlNzV5cnMiLCAidS4zMGRheV9ob3NwX3JlYWRtaXRfbWVkaWNhcmUiLCAidS4zMGRheV9ob3NwX3JlYWRtaXRfTkhyZXMiLCAidS5ob3NwXzZtb3NfTkhyZXMiLCAidS5ob3NwX21lZGljYXJlX2hvbWVoZWFsdGgiLCAidS5hdm9pZGFibGVfRVJfbWVkaWNhcmUiLCAidS50b3RfcmVpbWJfZW1wbG95ZXJfaW5zIiwgInUudG90X3JlaW1iX21lZGljYXJlIiwgImguc3VtbWFyeV9oZWFsdGh5X2xpdmVzIiwgImguZGVhdGhzX2FtZW5hYmxlIiwgImgueXJzX2xvc3RfcG90ZW50aWFsX2xpZmVfYmVmb3JlNzUiLCAiaC5kZWF0aHNfYnJlYXN0X2NhbmNlcl9GIiwgImguZGVhdGhzX2NvbG9yZWN0YWxfY2FuY2VyIiwgImguZGVhdGhzX3N1aWNpZGUiLCAiaC5kZWF0aHNfaW5mYW50X21vcnRhbGl0eSIsICJoLnBvb3JfaGVhbHRoX2FkdWx0IiwgImguc21va2VfYWR1bHQiLCAiaC5vYmVzZV9hZHVsdCIsICJoLm9iZXNlX2NoaWxkIiwgImgucG9vcl9kZW50YWxfYWR1bHQiLCAidS5wcmVtaXVtX2VtcF9wcml2YXRlIiwgInUucHJlbWl1bV9lbXBfcHJpdmF0ZV91bmFkaiIsICJ1LnJlaW1iX21lZGljYXJlX3VuYWRqIiwgInUuZGVhdGhzX2FtZW5hYmxlX2JsYWNrIiwgInUuZGVhdGhzX2FtZW5hYmxlX3doaXRlIiwgTkEsICJxLndpdGhfcHJldl9zY3JlZW5pbmdfYWJvdmU1MHlycyIsIE5BKQoKIyBSZXBsYWNlIHZhcmlhYmxlIG5hbWVzIHdpdGggYWJicmV2aWF0ZWQgdmVyc2lvbgpmb3IgKGkgaW4gMTo1NykgewogIGhlYWx0aF9pbmQkbWVhc3VyZSA8LSByZXBsYWNlKGhlYWx0aF9pbmQkbWVhc3VyZSwgaGVhbHRoX2luZCRtZWFzdXJlPT11bmlxdWVfbWVhc3VyZXNbaV0sIHVuaXF1ZV9tZWFzdXJlc19yZWxhYmVsbGVkW2ldKQp9CgojIFJlbW92ZSB0aGUgTkEncwpoZWFsdGhfaW5kIDwtIGhlYWx0aF9pbmRbIWlzLm5hKGhlYWx0aF9pbmQkbWVhc3VyZSksIF0KCiMgUmVtb3ZlIGR1cGxpY2F0ZXMKICAjIEJ5IHN0YXRlLCBtZWFzdXJlLnllYXIKaGVhbHRoX2luZCA8LSBoZWFsdGhfaW5kWyFkdXBsaWNhdGVkKGhlYWx0aF9pbmRbICwgMTozXSksIF0KCiMgSW50ZXJhY3QgbWVhc3VyZSBhbmQgeWVhcgpoZWFsdGhfaW5kJG1lYXN1cmVfeWVhciA8LSBpbnRlcmFjdGlvbihoZWFsdGhfaW5kJG1lYXN1cmUsIGhlYWx0aF9pbmQkeWVhcikKCiMgQ29udmVydCB0byBjaGFyYWN0ZXIgdmFyaWFibGUKaGVhbHRoX2luZCRtZWFzdXJlX3llYXIgPC0gYXMuY2hhcmFjdGVyKGhlYWx0aF9pbmQkbWVhc3VyZV95ZWFyKQoKIyBQcmUtcmVzaGFwZTogU3RvcmUgZXhpc3RpbmcgZGF0YSBhcyAibG9uZyIKaGVhbHRoX2luZF9sb25nIDwtIGhlYWx0aF9pbmQKCiMgUmVzaGFwZSB3aWRlCmhlYWx0aF9pbmQgPC0gYXMuZGF0YS5mcmFtZShjYmluZChoZWFsdGhfaW5kJHN0YXRlLCBoZWFsdGhfaW5kJG1lYXN1cmVfeWVhciwgaGVhbHRoX2luZCRyYXRlKSkKICAjIERyb3AgcmFuayBkYXRhIGZvciBub3cKbmFtZXMoaGVhbHRoX2luZCkgPC0gYygic3RhdGUiLCAibWVhc3VyZV95ZWFyIiwgInJhdGUiKQpoZWFsdGhfaW5kIDwtIHJlc2hhcGUoaGVhbHRoX2luZCwKICAgICAgICAgICAgICAgICAgICAgICAgaWR2YXIgPSAic3RhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICB0aW1ldmFyID0gIm1lYXN1cmVfeWVhciIsCiAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9ICJ3aWRlIikKCiMgRHJvcCAicmF0ZSIgZnJvbSB0aGUgbmFtZQpuYW1lcyhoZWFsdGhfaW5kKVsyOm5jb2woaGVhbHRoX2luZCldIDwtIHN1YnN0cihuYW1lcyhoZWFsdGhfaW5kKSwgNiwgbmNoYXIobmFtZXMoaGVhbHRoX2luZCkpKVsyOm5jb2woaGVhbHRoX2luZCldCgojIERyb3AgdmFyaWFibGVzIHdobyBoYXZlIGFsbCBlbnRyaWVzIGFzIE5BCiAgIyBEdWUgdG8gJ3VuYmFsYW5jZWQgcGFuZWwnIGluIHJlc2hhcGluZwogICMgRmlyc3QgY3JlYXRlIGEgdmVjdG9yIHRvIHJlY29yZCBpZiB2YXJpYWJsZSBpcyBhbGwgTkEKdmFyaWFibGVfYWxsX05BIDwtIHZlY3Rvcihtb2RlPSJsb2dpY2FsIiwgbGVuZ3RoPW5jb2woaGVhbHRoX2luZCkpCmZvciAoaiBpbiAxOm5jb2woaGVhbHRoX2luZCkpIHsKICBpZihzdW0oaXMubmEoaGVhbHRoX2luZFtbal1dKSk9PTUyKSB7CiAgICB2YXJpYWJsZV9hbGxfTkFbal0gPC0gVFJVRQogIH0KfQogICMgT25seSBrZWVwIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgTk9UIGFsbCBOQQpoZWFsdGhfaW5kIDwtIGhlYWx0aF9pbmRbICwgIXZhcmlhYmxlX2FsbF9OQV0KCiMgQ2hhbmdlIGZvcm1hdCBvZiB2YXJpYWJsZXMKICAjIFRvIGNoYXJhY3RlciB2YXJpYWJsZQpoZWFsdGhfaW5kJHN0YXRlIDwtIGFzLmNoYXJhY3RlcihoZWFsdGhfaW5kJHN0YXRlKQogICMgVG8gbnVtZXJpYyB2YXJpYWJsZQpmb3IgKGogaW4gYygyOjE2NCkpIHsKICBoZWFsdGhfaW5kW1tqXV0gPC0gYXMuY2hhcmFjdGVyKGhlYWx0aF9pbmRbW2pdXSkKICBoZWFsdGhfaW5kW1tqXV0gPC0gYXMubnVtZXJpYyhoZWFsdGhfaW5kW1tqXV0pCn0KCiMgU2F2ZSBVU0EgZGF0YSBzZXBhcmF0ZWx5CmhlYWx0aF9pbmRfVVNBIDwtIGhlYWx0aF9pbmRbaGVhbHRoX2luZCRzdGF0ZT09IlVuaXRlZCBTdGF0ZXMiLCBdCgojIERyb3AgVVNBIGFuZCBEQyBkYXRhCmhlYWx0aF9pbmQgPC0gaGVhbHRoX2luZFshKGhlYWx0aF9pbmQkc3RhdGUgJWluJSBjKCJVbml0ZWQgU3RhdGVzIiwgIkRpc3RyaWN0IG9mIENvbHVtYmlhIikpLCBdCgojIExhYmVsIHN0YXRlIGFiYnJldmlhdGlvbnMKaGVhbHRoX2luZCRzdGF0ZV9hYmIgPC0gc3RhdGVfYWJicmV2aWF0aW9ucwpoZWFsdGhfaW5kIDwtIGhlYWx0aF9pbmRbICwgYygxLCBuY29sKGhlYWx0aF9pbmQpLCAyOihuY29sKGhlYWx0aF9pbmQpLTEpKV0KCiMgRHJvcCByYXcgZGF0YQpybShoZWFsdGhfaW5kX3JhdykKCgojIyBDTEVBTiBERU1PR1JBUEhJQyAoMSkgREFUQQoKIyBEcm9wIHVubmVjZXNzYXJ5IHJvdyBhbmQgY29sdW1uCmRlbW9ncmFwaGljczEgPC0gZGVtb2dyYXBoaWNzMVstMSwtMV0KCiMgUmVuYW1lIHZhcmlhYmxlcwpjb2xuYW1lcyhkZW1vZ3JhcGhpY3MxKSA8LSBjKCJzdGF0ZSIsImluY29tZSIsInBvcHVsYXRpb24iLCAicHBsX2FnZTB0bzQiLCJwcGxfYWdlNXRvOSIsInBwbF9hZ2UxMHRvMTQiLCJwcGxfYWdlMTV0bzE5IiwicHBsX2FnZTIwdG8yNCIsICJwcGxfYWdlMjV0bzI5IiwicHBsX2FnZTMwdG8zNCIsInBwbF9hZ2UzNXRvMzkiLCJwcGxfYWdlNDB0bzQ0IiwgInBwbF9hZ2U0NXRvNDkiLCJwcGxfYWdlNTB0bzU0IiwicHBsX2FnZTU1dG81OSIsInBwbF9hZ2U2MHRvNjQiLCAicHBsX2FnZTY1dG82OSIsInBwbF9hZ2U3MHRvNzQiLCJwcGxfYWdlNzV0bzc5IiwicHBsX2FnZTgwdG84NCIsInBwbF9hZ2U4NXBsdXMiKQoKIyBEcm9wIG9ic2VydmF0aW9ucyBEQyBhbmQgUFIKZGVtb2dyYXBoaWNzMSA8LSBkZW1vZ3JhcGhpY3MxWyFkZW1vZ3JhcGhpY3MxJHN0YXRlPT0iRGlzdHJpY3Qgb2YgQ29sdW1iaWEiICYgIWRlbW9ncmFwaGljczEkc3RhdGU9PSJQdWVydG8gUmljbyIsIF0KCiMgTGFiZWwgc3RhdGUgYWJicmV2aWF0aW9ucwpkZW1vZ3JhcGhpY3MxJHN0YXRlX2FiYiA8LSBzdGF0ZV9hYmJyZXZpYXRpb25zCmRlbW9ncmFwaGljczEgPC0gZGVtb2dyYXBoaWNzMVsgLCBjKDEsIG5jb2woZGVtb2dyYXBoaWNzMSksIDI6KG5jb2woZGVtb2dyYXBoaWNzMSktMSkpXQoKIyBDaGFuZ2UgZm9ybWF0IG9mIHZhcmlhYmxlcwogICMgVG8gY2hhcmFjdGVyIHZhcmlhYmxlCmRlbW9ncmFwaGljczEkc3RhdGUgPC0gYXMuY2hhcmFjdGVyKGRlbW9ncmFwaGljczEkc3RhdGUpCiAgIyBUbyBudW1lcmljIHZhcmlhYmxlCmZvciAoaiBpbiBjKDM6bmNvbChkZW1vZ3JhcGhpY3MxKSkpIHsKICBkZW1vZ3JhcGhpY3MxW1tqXV0gPC0gYXMuY2hhcmFjdGVyKGRlbW9ncmFwaGljczFbW2pdXSkKICBkZW1vZ3JhcGhpY3MxW1tqXV0gPC0gYXMubnVtZXJpYyhkZW1vZ3JhcGhpY3MxW1tqXV0pCn0KCiMgQkVBIHJlZ2lvbnMKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uIDwtICIiCmRlbW9ncmFwaGljczEkQkVBX3JlZ2lvbltkZW1vZ3JhcGhpY3MxJHN0YXRlX2FiYiAlaW4lIGMoIk1FIiwgIk5IIiwgIlZUIiwgIk1BIiwgIkNUIiwgIlJJIildIDwtICJOZXcgRW5nbGFuZCIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiTlkiLCAiTkoiLCAiUEEiLCAiTUQiLCAiREUiKV0gPC0gIk1pZGVhc3QiCmRlbW9ncmFwaGljczEkQkVBX3JlZ2lvbltkZW1vZ3JhcGhpY3MxJHN0YXRlX2FiYiAlaW4lIGMoIldJIiwgIklMIiwgIk1JIiwgIklOIiwgIk9IIildIDwtICJHcmVhdCBMYWtlcyIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiV1YiLCAiS1kiLCAiVkEiLCAiVE4iLCAiTkMiLCAiU0MiLCAiQVIiLCAiTEEiLCAiTVMiLCAiQUwiLCAiR0EiLCAiRkwiKV0gPC0gIlNvdXRoZWFzdCIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiTkQiLCAiU0QiLCAiTkUiLCAiS1MiLCAiTU4iLCAiSUEiLCAiTU8iKV0gPC0gIlBsYWlucyIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiTVQiLCAiSUQiLCAiV1kiLCAiVVQiLCAiQ08iKV0gPC0gIlJvY2t5IE1vdW50YWlucyIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiQVoiLCAiTk0iLCAiVFgiLCAiT0siKV0gPC0gIlNvdXRod2VzdCIKZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW2RlbW9ncmFwaGljczEkc3RhdGVfYWJiICVpbiUgYygiV0EiLCAiT1IiLCAiQ0EiLCAiTlYiLCAiQUsiLCAiSEkiKV0gPC0gIkZhciBXZXN0IgoKIyBUYWcgaW5jb21lIGxldmVsIChjYXRlZ29yeSkKZGVtb2dyYXBoaWNzMSRpbmNvbWVfbGV2ZWwgPC0gIiIKZGVtb2dyYXBoaWNzMSRpbmNvbWVfbGV2ZWxbZGVtb2dyYXBoaWNzMSRpbmNvbWUgPj0gNjAwMDBdIDwtICJIaWdoIgpkZW1vZ3JhcGhpY3MxJGluY29tZV9sZXZlbFtkZW1vZ3JhcGhpY3MxJGluY29tZSA+PSA1MDAwMCAmIGRlbW9ncmFwaGljczEkaW5jb21lIDwgNjAwMDBdIDwtICJVcHBlciBNaWRkbGUiCmRlbW9ncmFwaGljczEkaW5jb21lX2xldmVsW2RlbW9ncmFwaGljczEkaW5jb21lID49IDQ1MDAwICYgZGVtb2dyYXBoaWNzMSRpbmNvbWUgPCA1MDAwMF0gPC0gIkxvd2VyIE1pZGRsZSIKZGVtb2dyYXBoaWNzMSRpbmNvbWVfbGV2ZWxbZGVtb2dyYXBoaWNzMSRpbmNvbWUgPCA0NTAwMF0gPC0gIkxvdyIKICAjIENvbnZlcnQgdG8gZmFjdG9yIHZhcmlhYmxlCmRlbW9ncmFwaGljczEkaW5jb21lX2xldmVsIDwtIGZhY3RvcihkZW1vZ3JhcGhpY3MxJGluY29tZV9sZXZlbCwgbGV2ZWxzID0gYygiTG93IiwgIkxvd2VyIE1pZGRsZSIsICJVcHBlciBNaWRkbGUiLCAiSGlnaCIpKQoKCiMjIENMRUFOIERFTU9HUkFQSElDICgyKSBEQVRBCgpjb2xuYW1lcyhkZW1vZ3JhcGhpY3MyKSA8LSBkZW1vZ3JhcGhpY3MyWzIsIF0KCiMgRHJvcCBmaXJzdCBmZXcgcm93cyAobm9uLW9ic2VydmF0aW9ucykKZGVtb2dyYXBoaWNzMiA8LSBkZW1vZ3JhcGhpY3MyWy0oMToyKSwgXQoKIyBEcm9wIGNvdW50eS1sZXZlbCBkYXRhLCAga2VlcCBzdGF0ZS1sZXZlbCBkYXRhIG9ubHkKZGVtb2dyYXBoaWNzMiA8LSBkZW1vZ3JhcGhpY3MyW2RlbW9ncmFwaGljczIkQXJlYV9OYW1lID09ICJVbml0ZWQgU3RhdGVzIiB8IGRlbW9ncmFwaGljczIkU3RhdGUgIT0gbGFnKGRlbW9ncmFwaGljczIkU3RhdGUpLCBdCgojIEtlZXAgb25seSBjb2x1bW5zIG9mIHBvcHVsYXRpb24gZnJvbSAyMDEwIHRvIDIwMTUKZGVtb2dyYXBoaWNzMiA8LSBkZW1vZ3JhcGhpY3MyWyAsIGMoIlN0YXRlIiwgIkFyZWFfTmFtZSIsICJQT1BfRVNUSU1BVEVfMjAxMCIsICJQT1BfRVNUSU1BVEVfMjAxMSIsICJQT1BfRVNUSU1BVEVfMjAxMiIsICJQT1BfRVNUSU1BVEVfMjAxMyIsICJQT1BfRVNUSU1BVEVfMjAxNCIsICJQT1BfRVNUSU1BVEVfMjAxNSIpXQoKIyBDaGFuZ2UgZm9ybWF0IG9mIHZhcmlhYmxlcwogICMgVG8gY2hhcmFjdGVyIHZhcmlhYmxlCmZvciAoaiBpbiBjKDM6OCkpIHsKICBkZW1vZ3JhcGhpY3MyW1tqXV0gPC0gYXMubnVtZXJpYyhkZW1vZ3JhcGhpY3MyW1tqXV0pCn0KCiMgUmVuYW1lIHZhcmlhYmxlcwpjb2xuYW1lcyhkZW1vZ3JhcGhpY3MyKSA8LSBjKCJzdGF0ZV9hYmIiLCAic3RhdGUiLCAicG9wdWxhdGlvbl8yMDEwIiwgInBvcHVsYXRpb25fMjAxMSIsICJwb3B1bGF0aW9uXzIwMTIiLCAicG9wdWxhdGlvbl8yMDEzIiwgInBvcHVsYXRpb25fMjAxNCIsICJwb3B1bGF0aW9uXzIwMTUiKQoKCiMjIENMRUFOIEVMRUNUSU9OIERBVEEKCiMgS2VlcCBvbmx5IDIwMTIgYW5kIDIwMDggZGF0YSwgYW5kIGRhdGEgZm9yIHRoZSA1MCBzdGF0ZXMKZWxlY3Rpb24gPC0gZWxlY3Rpb25bIDQ6NTMgLCBjKCJYMCIsICJYNSIsICJYNiIsICJYOSIsICJYMTAiKV0KCiMgUmVuYW1lIHZhcmlhYmxlcwpjb2xuYW1lcyhlbGVjdGlvbikgPC0gYygic3RhdGUiLCAiRGVtX3BjdF8yMDEyIiwgIlJlcF9wY3RfMjAxMiIsICJEZW1fcGN0XzIwMDgiLCAiUmVwX3BjdF8yMDA4IikKCiMgQWRkIHN0YXRlIGFiYnJldmlhdGlvbnMKICAjIE1hdGNoIHdpdGggbG9vay11cCB0YWJsZQplbGVjdGlvbiRzdGF0ZV9hYmIgPC0gc3RhdGVfYWJiX2xvb2t1cCRzdGF0ZV9hYmJbbWF0Y2goZWxlY3Rpb24kc3RhdGUsIHN0YXRlX2FiYl9sb29rdXAkc3RhdGUpXQoKIyBDaGFuZ2UgZm9ybWF0IG9mIHZhcmlhYmxlcwogICMgVG8gbnVtZXJpYyB2YXJpYWJsZQpmb3IgKGogaW4gYyg0OjYpKSB7CiAgZWxlY3Rpb25bW2pdXSA8LSBhcy5udW1lcmljKGVsZWN0aW9uW1tqXV0pCn0KCiMgQ2FsY3VsYXRlIHdpbm5pbmcgcGFydHkgZm9yIGVhY2ggc3RhdGUKZWxlY3Rpb24kcGFydHlfMjAxMiA8LSBpZmVsc2UoZWxlY3Rpb24kRGVtX3BjdF8yMDEyID4gZWxlY3Rpb24kUmVwX3BjdF8yMDEyLCAiRGVtb2NyYXRpYyIsICJSZXB1YmxpY2FuIikKZWxlY3Rpb24kcGFydHlfMjAwOCA8LSBpZmVsc2UoZWxlY3Rpb24kRGVtX3BjdF8yMDA4ID4gZWxlY3Rpb24kUmVwX3BjdF8yMDA4LCAiRGVtb2NyYXRpYyIsICJSZXB1YmxpY2FuIikKCiMgUmVvcmRlciB2YXJpYWJsZXMKZWxlY3Rpb24gPC0gZWxlY3Rpb25bICwgYygic3RhdGUiLCAic3RhdGVfYWJiIiwgIkRlbV9wY3RfMjAxMiIsICJSZXBfcGN0XzIwMTIiLCAicGFydHlfMjAxMiIsICJEZW1fcGN0XzIwMDgiLCAiUmVwX3BjdF8yMDA4IiwgInBhcnR5XzIwMDgiKV0KYGBgCgpgYGB7cn0KIyMgRVhQT1JUIERBVEFTRVRTIEZPUiBTSElOWSBVU0UKI3dyaXRlX2NzdihpbnN1cmFuY2UsICIvVXNlcnMvZ3JhY2Vrb25neXgvRG9jdW1lbnRzLyo2X0RhdGEgU2NpZW5jZS9RTVNTIEc0MDYzIERhdGEgVmlzdWFsaXphdGlvbi9GaW5hbCBQcm9qZWN0L0RhdGEvc2hpbnlfaW5zdXJhbmNlLmNzdiIpCgpgYGAKCgojICgxKSBIZWFsdGggSW5zdXJhbmNlIENvdmVyYWdlCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBTT01FIERBVEEgUFJFUEFSQVRJT04KCiMgTG9vay11cCBpbmZvcm1hdGlvbiBpbnRvIGluc3VyYW5jZSBhbmQgaW5zdXJhbmNlX2xvbmcsIG9uOgogICMgUGFydHkgKDIwMTIpCmluc3VyYW5jZV9sb25nJHBhcnR5XzIwMTIgPC0gZWxlY3Rpb24kcGFydHlfMjAxMlttYXRjaChpbnN1cmFuY2VfbG9uZyRzdGF0ZSwgZWxlY3Rpb24kc3RhdGUpXQppbnN1cmFuY2UkcGFydHlfMjAxMiA8LSBlbGVjdGlvbiRwYXJ0eV8yMDEyW21hdGNoKGluc3VyYW5jZSRzdGF0ZSwgZWxlY3Rpb24kc3RhdGUpXQogICMgQkVBIHJlZ2lvbgppbnN1cmFuY2VfbG9uZyRCRUFfcmVnaW9uIDwtIGRlbW9ncmFwaGljczEkQkVBX3JlZ2lvblttYXRjaChpbnN1cmFuY2VfbG9uZyRzdGF0ZSwgZGVtb2dyYXBoaWNzMSRzdGF0ZSldCmluc3VyYW5jZSRCRUFfcmVnaW9uIDwtIGRlbW9ncmFwaGljczEkQkVBX3JlZ2lvblttYXRjaChpbnN1cmFuY2Ukc3RhdGUsIGRlbW9ncmFwaGljczEkc3RhdGUpXQogICMgSW5jb21lIGxldmVsCmluc3VyYW5jZV9sb25nJGluY29tZV9sZXZlbCA8LSBkZW1vZ3JhcGhpY3MxJGluY29tZV9sZXZlbFttYXRjaChpbnN1cmFuY2VfbG9uZyRzdGF0ZSwgZGVtb2dyYXBoaWNzMSRzdGF0ZSldCmluc3VyYW5jZSRpbmNvbWVfbGV2ZWwgPC0gZGVtb2dyYXBoaWNzMSRpbmNvbWVfbGV2ZWxbbWF0Y2goaW5zdXJhbmNlJHN0YXRlLCBkZW1vZ3JhcGhpY3MxJHN0YXRlKV0KCiMgQWxzbyBmaW5kIG5hdGlvbi13aWRlIHRyZW5kIGZvciBpbnN1cmFuY2UKaW5zdXJhbmNlX2xvbmdfVVMgPC0gZGF0YS5mcmFtZSgieWVhciIgPSBjKDIwMDgsIDIwMDksIDIwMTAsIDIwMTEsIDIwMTIsIDIwMTMsIDIwMTQsIDIwMTUpLCAidW5pbnN1cmVkX3BjdCIgPSBjKDE2LjgsIDE3LjUsIDE4LjIsIDE3LjIsIDE2LjksIDE2LjYsIDEzLjMsIDEwLjUpKQpgYGAKCgpUaGUgZm9sbG93aW5nIGZpZ3VyZSBkaXNwbGF5cyB0aGUgdHJlbmQgaW4gdGhlIHVuaW5zdXJlZCByYXRlIGJldHdlZW4gMjAwOCBhbmQgMjAxNS4gUmVzdWx0cyBhcmUgc2hvd24gZm9yIHRoZSBVU0EgYXZlcmFnZSAoaW4gYmxhY2spLCBhcyB3ZWxsIGFzIGZvciBldmVyeSBpbmRpdmlkdWFsIHN0YXRlIChpbiBjb2xvcikuIFRoZSBzdGF0ZXMgYXJlIGdyb3VwZWQgYW5kIGNvbG9yLWNvZGVkIGJ5IHJlZ2lvbiB0byBmYWNpbGl0YXRlIGlkZW50aWZpY2F0aW9uLCB3aGVyZSBvbmUgY2FuIHRvZ2dsZSB0aGUgZGlzcGxheSB0byBzaG93IGEgcGFydGljdWxhciByZWdpb24gdG8gbG9jYXRlIGEgcGFydGljdWxhciBzdGF0ZS4gV2Ugc2VlIGEgY2xlYXIgZG93bndhcmQgdHJlbmQgaW4gdGhlIHVuaW5zdXJlZCByYXRlIG9uY2UgbW9zdCBvZiB0aGUgQWZmb3JkYWJsZSBDYXJlIEFjdCAoQUNBKSBwcm92aXNpb25zIHdlcmUgaW1wbGVtZW50ZWQgaW4gMjAxNC4KCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgMQoKcGxvdDEgPC0gKGdncGxvdChpbnN1cmFuY2VfbG9uZywgYWVzKHllYXIsIHVuaW5zdXJlZF9wY3QpKSAKICAgICAgICAgICsgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEJFQV9yZWdpb24sIGdyb3VwID0gc3RhdGUsIGxhYmVsID0gdW5pbnN1cmVkX251bSkpCiAgICAgICAgICArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDIwMDgsIDIwMDksIDIwMTAsIDIwMTEsIDIwMTIsIDIwMTMsIDIwMTQsIDIwMTUpKQogICAgICAgICAgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYyg1LCAxMCwgMTUsIDIwLCAyNSwgMzApKQogICAgICAgICAgKyBsYWJzKHggPSAiWWVhciIsIHkgPSAiJSBVbmluc3VyZWQiLCBjb2xvciA9ICJSZWdpb24iKQogICAgICAgICAgKyBnZW9tX2xpbmUoZGF0YSA9IGluc3VyYW5jZV9sb25nX1VTLCBsd2QgPSAwLjgpCiAgICAgICAgICArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAiZ3JheTMwIikKICAgICAgICAgICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxNCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmF5MzAiKQogICAgICAgICAgKyBhbm5vdGF0ZSgidGV4dCIseCA9IDIwMDkuNCwgeSA9IDI1LCBsYWJlbCA9ICJPYmFtYSBcbnNpZ25zIEFDQSIsIGNvbG9yID0gImJsYWNrIixmb250ZmFjZSA9IDIsIHNpemUgPSAzKQogICAgICAgICAgKyBhbm5vdGF0ZSgidGV4dCIseCA9IDIwMTMuNCwgeSA9IDI0LjUsIGxhYmVsID0gIk1vc3QgQUNBIFxucHJvdmlzaW9ucyBcbnRha2UgZWZmZWN0IiwgY29sb3IgPSAiYmxhY2siLGZvbnRmYWNlID0gMiwgc2l6ZSA9IDMpCiAgICAgICAgICArIGFubm90YXRlKCJ0ZXh0Iix4ID0gMjAxNC4yLCB5ID0gMTEsIGxhYmVsID0gIlVTQSBcbkF2ZXJhZ2UiLCBjb2xvciA9ICJibGFjayIsZm9udGZhY2UgPSAyLCBzaXplID0gMykKICAgICAgICAgICsgZ2d0aXRsZSgiQ2hhbmdlIGluIFBlcmNlbnRhZ2UgVW5pbnN1cmVkIGJ5IFN0YXRlLCBcbmZyb20gMjAwOCB0byAyMDE1IikKICAgICAgICAgICsgdGhlbWVfbWluaW1hbCgpCiAgICAgICAgICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsIGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSkpCmdncGxvdGx5KHBsb3QxLCBkeW5hbWljVGlja3MgPSBGQUxTRSwgdG9vbHRpcCA9IGMoInN0YXRlIiwgInllYXIiLCAidW5pbnN1cmVkX3BjdCIsICJ1bmluc3VyZWRfbnVtIikpCmBgYAoKCkluIHRoZSBmb2xsb3dpbmcgcGxvdCwgSSBleHBsb3JlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gRGVtb2NyYXRpYyBhbmQgUmVwdWJsaWNhbiBzdGF0ZXMsIGJhc2VkIG9uIHRoZSAyMDEyIFVTIFByZXNpZGVudGlhbCBFbGVjdGlvbiByZXN1bHRzLiBJdCBpcyBjbGVhciB0aGF0IHRoZSBkZW1vY3JhdGljIHN0YXRlcyBsYXJnZWx5IGhhdmUgYSBsb3dlciB1bmluc3VyZWQgcmF0ZSB0aGFuIHRoZSBSZXB1YmxpY2FuIHN0YXRlcywgdGhvdWdoIGJvdGggZ3JvdXBzIGV4cGVyaWVuY2VkIGRlY2xpbmVzIGluIHRoZSB1bmluc3VyZWQgcmF0ZXMgaW4gMjAxNC4KCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgMgpwbG90MiA8LSAoZ2dwbG90KGluc3VyYW5jZV9sb25nLCBhZXMoeWVhciwgdW5pbnN1cmVkX3BjdCkpIAogICAgICAgICAgKyBnZW9tX2xpbmUoYWVzKGNvbG9yID0gcGFydHlfMjAxMiwgZ3JvdXAgPSBzdGF0ZSwgbGFiZWwgPSB1bmluc3VyZWRfbnVtKSkKICAgICAgICAgICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMjAwOCwgMjAwOSwgMjAxMCwgMjAxMSwgMjAxMiwgMjAxMywgMjAxNCwgMjAxNSkpCiAgICAgICAgICArIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDUsIDEwLCAxNSwgMjAsIDI1LCAzMCkpCiAgICAgICAgICArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJzdGVlbCBibHVlIiwgImZpcmVicmljazEiKSkgCiAgICAgICAgICArIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICIlIFVuaW5zdXJlZCIsIGNvbG9yID0gIlBhcnR5IFxuKDIwMTIgV2lubmVyKSIpCiAgICAgICAgICArIGdlb21fbGluZShkYXRhID0gaW5zdXJhbmNlX2xvbmdfVVMsIGx3ZCA9IDEpCiAgICAgICAgICArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMTAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAiZ3JheTMwIikKICAgICAgICAgICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAxNCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmF5MzAiKQogICAgICAgICAgKyBhbm5vdGF0ZSgidGV4dCIseCA9IDIwMDkuNCwgeSA9IDI1LCBsYWJlbCA9ICJPYmFtYSBcbnNpZ25zIEFDQSIsIGNvbG9yID0gImJsYWNrIixmb250ZmFjZSA9IDIsIHNpemUgPSAzKQogICAgICAgICAgKyBhbm5vdGF0ZSgidGV4dCIseCA9IDIwMTMuNCwgeSA9IDI0LjUsIGxhYmVsID0gIk1vc3QgQUNBIFxucHJvdmlzaW9ucyBcbnRha2UgZWZmZWN0IiwgY29sb3IgPSAiYmxhY2siLGZvbnRmYWNlID0gMiwgc2l6ZSA9IDMpCiAgICAgICAgICArIGFubm90YXRlKCJ0ZXh0Iix4ID0gMjAxNC4yLCB5ID0gMTEsIGxhYmVsID0gIlVTQSBcbkF2ZXJhZ2UiLCBjb2xvciA9ICJibGFjayIsZm9udGZhY2UgPSAyLCBzaXplID0gMykKICAgICAgICAgICsgZ2d0aXRsZSgiQ2hhbmdlIGluIFBlcmNlbnRhZ2UgVW5pbnN1cmVkIGJ5IFBhcnR5LCBcbmZyb20gMjAwOCB0byAyMDE1IikKICAgICAgICAgICsgdGhlbWVfbWluaW1hbCgpCiAgICAgICAgICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsIGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSkpCmdncGxvdGx5KHBsb3QyLCBkeW5hbWljVGlja3MgPSBGQUxTRSwgIHRvb2x0aXAgPSBjKCJzdGF0ZSIsICJ5ZWFyIiwgInVuaW5zdXJlZF9wY3QiLCAidW5pbnN1cmVkX251bSIpKQpgYGAKCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgMwoKIyBTdWJzZXQgcmVsZXZhbnQgdmFyaWFibGVzCmluc3VyYW5jZV8yMDE1IDwtIGluc3VyYW5jZVsgLCBjKCJzdGF0ZSIsICJ1bmluc3VyZWRfcGN0XzIwMTUiLCAiaW5zdXJlZF9wY3RfMjAxNSIsICJwYXJ0eV8yMDEyIiwgIkJFQV9yZWdpb24iLCAiaW5jb21lX2xldmVsIildCgojIEJveHBsb3RzIGJ5IHBhcnR5CnBsb3QzYSA8LSAoZ2dwbG90KGluc3VyYW5jZV8yMDE1LCBhZXMoeCA9IHJlb3JkZXIocGFydHlfMjAxMiwgaW5zdXJlZF9wY3RfMjAxNSksIHkgPSBpbnN1cmVkX3BjdF8yMDE1KSkgCiAgICAgICAgICArIGdlb21fYm94cGxvdChhZXMoZmlsbCA9IHBhcnR5XzIwMTIsIGxhYmVsID0gaW5zdXJlZF9wY3RfMjAxNSksIGNvbG9yID0gImdyYXkzMCIpCiAgICAgICAgICArIGNvb3JkX2ZsaXAoKQogICAgICAgICAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJzdGVlbCBibHVlIiwgImZpcmVicmljayIpKQogICAgICAgICAgKyBnZ3RpdGxlKCJEZW1vY3JhdGljIHZzLiBSZXB1YmxpY2FuIFN0YXRlcyIpCiAgICAgICAgICArIHRoZW1lX21pbmltYWwoKQogICAgICAgICAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBoanVzdCA9IDAuMzcsIHNpemUgPSAxMiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpKQoKIyBCb3hwbG90cyBieSBCRUEgcmVnaW9uCnBsb3QzYiA8LSAoZ2dwbG90KGluc3VyYW5jZV8yMDE1LCBhZXMoeCA9IHJlb3JkZXIoQkVBX3JlZ2lvbiwgaW5zdXJlZF9wY3RfMjAxNSksIHkgPSBpbnN1cmVkX3BjdF8yMDE1KSkgCiAgICAgICAgICArIGdlb21fYm94cGxvdChhZXMoZmlsbCA9IEJFQV9yZWdpb24sIGxhYmVsID0gaW5zdXJlZF9wY3RfMjAxNSksIGNvbG9yID0gImdyYXkzMCIpCiAgICAgICAgICArIGNvb3JkX2ZsaXAoKQogICAgICAgICAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBicmV3ZXIucGFsKG4gPSA4LCBuYW1lID0gIkRhcmsyIikpCiAgICAgICAgICArIGdndGl0bGUoIkJ5IEJ1cmVhdSBvZiBFY29ub21pYyBBbmFseXNpcyAoQkVBKSBSZWdpb24iKQogICAgICAgICAgKyB0aGVtZV9taW5pbWFsKCkKICAgICAgICAgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgaGp1c3QgPSAwLjI0LCBzaXplID0gMTIpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSkKCiMgQm94cGxvdHMgYnkgaW5jb21lIGxldmVsCnBsb3QzYyA8LSAoZ2dwbG90KGluc3VyYW5jZV8yMDE1LCBhZXMoeCA9IGluY29tZV9sZXZlbCwgeSA9IGluc3VyZWRfcGN0XzIwMTUpKSAKICAgICAgICAgICsgZ2VvbV9ib3hwbG90KGFlcyhmaWxsID0gaW5jb21lX2xldmVsLCBsYWJlbCA9IGluc3VyZWRfcGN0XzIwMTUpLCBjb2xvciA9ICJncmF5MzAiKQogICAgICAgICAgKyBjb29yZF9mbGlwKCkKICAgICAgICAgICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYnJld2VyLnBhbChuID0gNCwgbmFtZSA9ICJEYXJrMiIpKQogICAgICAgICAgKyBsYWJzKHggPSAiIiwgeSA9ICIlIEluc3VyZWQgKDIwMTUpIikKICAgICAgICAgICsgZ2d0aXRsZSgiQnkgU3RhdGUncyBJbmNvbWUgTGV2ZWwiKQogICAgICAgICAgKyB0aGVtZV9taW5pbWFsKCkKICAgICAgICAgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgaGp1c3QgPSAwLjM5LCBzaXplID0gMTIpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkpCgojIENvbWJpbmUgcGxvdHMgdmVydGljYWxseQpncmlkLmFycmFuZ2UocGxvdDNhLCBwbG90M2IsIHBsb3QzYywgbnJvdyA9IDMsIHRvcCA9ICIyMDE1IEluc3VyYW5jZSBSYXRlcyBhdCBhIEdsYW5jZSIpCmBgYAoKYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCB0aWR5ID0gVFJVRX0KIyMgU09NRSBEQVRBIFJFU0hBUElORwoKIyBSZXNoYXBlIGFjYV9nZW5lcmFsIChsb25nKSwga2VlcGluZyB0aGUgaW50ZXJlc3RpbmcgcXVhbnRpdGllcwogICMgSW1wb3J0IHVuaW5zdXJlZCBudW1iZXIgKDIwMTUpCmFjYV9nZW5lcmFsJHVuaW5zX2FsbF8xNSA8LSBpbnN1cmFuY2UkdW5pbnN1cmVkX251bV8yMDE1W21hdGNoKGFjYV9nZW5lcmFsJHN0YXRlLCBpbnN1cmFuY2Ukc3RhdGUpXQogICMgS2VlcCBvbmx5IHNlbGVjdCB2YXJpYWJsZXMKYWNhX2dlbmVyYWxfbG9uZyA8LSBhY2FfZ2VuZXJhbFsgLCBjKCJzdGF0ZSIsICJzdGF0ZV9hYmIiLCAiY292X2VtcCIsICJjb3ZfbWt0X3BsYW5fMTYiLCAibWVkaWNhaWRfZW5yb2xsXzE2IiwgIm1lZGljYXJlX2Vucm9sbF8xNiIsICJ1bmluc19hbGxfMTUiKV0KICAjIFRoZSBhY3R1YWwgcmVzaGFwaW5nCmFjYV9nZW5lcmFsX2xvbmcgPC0gcmVzaGFwZShhY2FfZ2VuZXJhbF9sb25nLCAKICAgICAgICAgICAgICAgICAgICAgIHZhcnlpbmcgPSBjKCJjb3ZfZW1wIiwgImNvdl9ta3RfcGxhbl8xNiIsICJtZWRpY2FpZF9lbnJvbGxfMTYiLCAibWVkaWNhcmVfZW5yb2xsXzE2IiwgInVuaW5zX2FsbF8xNSIpLAogICAgICAgICAgICAgICAgICAgICAgdi5uYW1lcyA9ICJOdW1iZXIiLAogICAgICAgICAgICAgICAgICAgICAgdGltZXZhciA9ICJTb3VyY2UiLAogICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSBjKCJFbXBsb3llciIsICJNYXJrZXRwbGFjZSIsICJNZWRpY2FpZCAvIENISVAiLCAiTWVkaWNhcmUiLCAiVW5pbnN1cmVkIiksCiAgICAgICAgICAgICAgICAgICAgICBuZXcucm93Lm5hbWVzID0gMToxMDAwLAogICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gImxvbmciKQoKIyBMb29rLXVwIGluZm9ybWF0aW9uIGludG8gYWNhX2dlbmVyYWxfbG9uZywgb246CiAgIyBQYXJ0eSAoMjAxMikKYWNhX2dlbmVyYWxfbG9uZyRwYXJ0eV8yMDEyIDwtIGVsZWN0aW9uJHBhcnR5XzIwMTJbbWF0Y2goYWNhX2dlbmVyYWxfbG9uZyRzdGF0ZSwgZWxlY3Rpb24kc3RhdGUpXQogICMgQkVBIHJlZ2lvbgphY2FfZ2VuZXJhbF9sb25nJEJFQV9yZWdpb24gPC0gZGVtb2dyYXBoaWNzMSRCRUFfcmVnaW9uW21hdGNoKGFjYV9nZW5lcmFsX2xvbmckc3RhdGUsIGRlbW9ncmFwaGljczEkc3RhdGUpXQogICMgSW5jb21lIGxldmVsCmFjYV9nZW5lcmFsX2xvbmckaW5jb21lX2xldmVsIDwtIGRlbW9ncmFwaGljczEkaW5jb21lX2xldmVsW21hdGNoKGFjYV9nZW5lcmFsX2xvbmckc3RhdGUsIGRlbW9ncmFwaGljczEkc3RhdGUpXQogICMgUG9wdWxhdGlvbgphY2FfZ2VuZXJhbF9sb25nJHBvcHVsYXRpb25fMjAxNSA8LSBkZW1vZ3JhcGhpY3MyJHBvcHVsYXRpb25fMjAxNVttYXRjaChhY2FfZ2VuZXJhbF9sb25nJHN0YXRlLCBkZW1vZ3JhcGhpY3MyJHN0YXRlKV0KCiMgQ2FsY3VsYXRlIHBlcmNlbnRhZ2UgZnJvbSBudW1iZXIgYW5kIHBvcHVsYXRpb24KYWNhX2dlbmVyYWxfbG9uZyRwZXJjZW50YWdlIDwtIGFjYV9nZW5lcmFsX2xvbmckTnVtYmVyIC8gYWNhX2dlbmVyYWxfbG9uZyRwb3B1bGF0aW9uXzIwMTUgKiAxMDAKYGBgCgoKTmV4dCwgSSBpbnZlc3RpZ2F0ZSB0aGUgbWFpbiBoZWFsdGggaW5zdXJhbmNlIGFuZCBjb3ZlcmFnZSBzb3VyY2VzLCBuYW1lbHkgZW1wbG95ZXIgY292ZXJhZ2UsIHRoZSBpbmRpdmlkdWFsIG1hcmtldHBsYWNlLCBNZWRpY2FpZCAvIENoaWxkcmVucycgSGVhbHRoIEluc3VyYW5jZSBQcm9ncmFtIChDSElQKSwgYW5kIE1lZGljYXJlIGZvciB0aGUgYWdlZC4gSSBicm9rZSBkb3duIHRoZSByZXN1bHRzIGJ5IHBhcnR5IGFuZCBpbmNvbWUgbGV2ZWwsIHRha2luZyBhIHNpbXBsZSAodW53ZWlnaHRlZCkgYXZlcmFnZSBhY3Jvc3MgdGhlIHN0YXRlcyBpbiB0aGUgY2F0ZWdvcmllcy4gV2Ugb2JzZXJ2ZSB0aGF0IGVtcGxveWVyIGNvdmVyYWdlIHJhdGVzIGluY3JlYXNlIGFzIGluY29tZSBsZXZlbCBpbmNyZWFzZXMsIGVzcGVjaWFsbHkgZm9yIERlbW9jcmF0aWMgc3RhdGVzLiBEZW1vY3JhdGljIGFuZCBsb3cgaW5jb21lIHN0YXRlcyBoYXZlIG1vcmUgcGVvcGxlIG9uIE1lZGljYWlkIC8gQ0hJUCB0aGFuIFJlcHVibGljYW4gYW5kIGxvdyBpbmNvbWUgc3RhdGVzLgoKYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCB0aWR5ID0gVFJVRX0KIyMgUExPVCA0CgphY2FfZ2VuZXJhbF9sb25nX2J5X3BhcnR5X2luY29tZSA8LSBkZHBseShhY2FfZ2VuZXJhbF9sb25nLCBjKCJwYXJ0eV8yMDEyIiwgImluY29tZV9sZXZlbCIsICJTb3VyY2UiKSwgc3VtbWFyaXNlLCBhdmdfcGN0ID0gbWVhbihwZXJjZW50YWdlKSkKCnBsb3Q0IDwtIChnZ3Bsb3QoYWNhX2dlbmVyYWxfbG9uZ19ieV9wYXJ0eV9pbmNvbWUsIGFlcyhpbmNvbWVfbGV2ZWwsIGF2Z19wY3QsIGZpbGwgPSBTb3VyY2UpKQogICAgICAgICAgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgZmFjZXRfZ3JpZChwYXJ0eV8yMDEyIH4gLikKICAgICAgICAgICsgbGFicyh4ID0gIkluY29tZSBMZXZlbCIsIHkgPSAiQXZlcmFnZSAlIGluIFN0YXRlIiwgY29sb3IgPSAiU291cmNlIG9mIFxuSW5zdXJhbmNlIikKICAgICAgICAgICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYnJld2VyLnBhbChuID0gNiwgbmFtZSA9ICJEYXJrMiIpW2MoMTozLDYsNCldKQogICAgICAgICAgKyBnZ3RpdGxlKCJTb3VyY2VzIG9mIEhlYWx0aCBJbnN1cmFuY2UsIFxuYnkgUGFydHkgYW5kIEluY29tZSBMZXZlbCIpCiAgICAgICAgICArIHRoZW1lX21pbmltYWwoKQogICAgICAgICAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBoanVzdCA9IDAsIHNpemUgPSAxMikpKQpnZ3Bsb3RseShwbG90NCwgdG9vbHRpcCA9IGMoImluY29tZV9sZXZlbCIsICJTb3VyY2UiLCAiYXZnX3BjdCIpKQpgYGAKCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBQUkVQQVJBVElPTiBGT1IgRlVSVEhFUiBQTE9UUyAoSU5DTFVESU5HIERBVEEgVEFCTEUpCgojIFdhbnQgdG8gY29tYmluZSBpbmZvcm1hdGlvbiBvbiBpbnN1cmFuY2UgY292ZXJhZ2Ugd2l0aCBrZXkgaW5mb3JtYXRpb24gb24gaGVhbHRoIG91dGNvbWVzL2FjY2VzcyBhbmQgYWZmb3JkYWJpbGl0eQoKa2V5X2luZGljYXRvcnMgPC0gc3RhdGVfYWJiX2xvb2t1cAoKIyMgTWVyZ2UgaW4gaW5mb3JtYXRpb24gdG8gdGhlIGRhdGEgdGFibGUgb24gdGhlIGZvbGxvd2luZwoKIyBEZW1vZ3JhcGhpYyBJbmZvcm1hdGlvbgogICMgSW5jb21lIGxldmVsCmtleV9pbmRpY2F0b3JzJGluY29tZV9sZXZlbCA8LSBkZW1vZ3JhcGhpY3MxJGluY29tZV9sZXZlbFttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGRlbW9ncmFwaGljczEkc3RhdGVfYWJiKV0KCiMgSW5zdXJhbmNlIENvdmVyYWdlCiAgIyBQZXJjZW50YWdlIGluc3VyZWQgKDIwMTUpCmtleV9pbmRpY2F0b3JzJGluc3VyZWRfcGN0XzIwMTUgPC0gaW5zdXJhbmNlJGluc3VyZWRfcGN0XzIwMTVbbWF0Y2goa2V5X2luZGljYXRvcnMkc3RhdGVfYWJiLCBpbnN1cmFuY2Ukc3RhdGVfYWJiKV0KICAjIFBlcmNlbnRhZ2UgaW5zdXJlZCAoMjAxNCkKa2V5X2luZGljYXRvcnMkaW5zdXJlZF9wY3RfMjAxNCA8LSBpbnN1cmFuY2UkaW5zdXJlZF9wY3RfMjAxNFttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGluc3VyYW5jZSRzdGF0ZV9hYmIpXQogICMgSW5kaWNhdG9yOiBXaGV0aGVyIHN0YXRlIGhhcyBleHBhbmRlZCBtZWRpY2FyZQprZXlfaW5kaWNhdG9ycyRzdGF0ZV9oYXNfZXhwYW5kZWQgPC0gYWNhX2dlbmVyYWwkc3RhdGVfaGFzX2V4cGFuZGVkW21hdGNoKGtleV9pbmRpY2F0b3JzJHN0YXRlX2FiYiwgYWNhX2dlbmVyYWwkc3RhdGVfYWJiKV0KCiMgSGVhbHRoIG91dGNvbWVzIGFuZCBhY2Nlc3MKICAjIE1vcnRhbGl0eSBhbWVuYWJsZSB0byBoZWFsdGggY2FyZSwgZGVhdGhzIHBlciAxMDAwMCBwb3B1bGF0aW9uCmtleV9pbmRpY2F0b3JzJGRlYXRoc19hbWVuYWJsZV8yMDE0IDwtIGhlYWx0aF9pbmQkaC5kZWF0aHNfYW1lbmFibGUuMjAxNCBbbWF0Y2goa2V5X2luZGljYXRvcnMkc3RhdGVfYWJiLCBoZWFsdGhfaW5kJHN0YXRlX2FiYildCiAgIyBZZWFycyBvZiBQb3RlbnRpYWwgTGlmZSBMb3N0IGJlZm9yZSA3NQprZXlfaW5kaWNhdG9ycyR5ZWFyc19saWZlX2xvc3QgPC0gaGVhbHRoX2luZCRoLnlyc19sb3N0X3BvdGVudGlhbF9saWZlX2JlZm9yZTc1LjIwMTQgW21hdGNoKGtleV9pbmRpY2F0b3JzJHN0YXRlX2FiYiwgaGVhbHRoX2luZCRzdGF0ZV9hYmIpXQogICMgQWR1bHRzIHdpdGggYSB1c3VhbCBzb3VyY2Ugb2YgY2FyZSAoJSkKa2V5X2luZGljYXRvcnMkdXN1YWxfY2FyZV8yMDE1IDwtIGhlYWx0aF9pbmQkcS53aXRoX3VzdWFsX2NhcmVfYWR1bHQuMjAxNSBbbWF0Y2goa2V5X2luZGljYXRvcnMkc3RhdGVfYWJiLCBoZWFsdGhfaW5kJHN0YXRlX2FiYildCiAgIyBBZHVsdHMgd2l0aCBhZ2UvZ2VuZGVyLWFwcHJvcHJpYXRlIGNhbmNlciBzY3JlZW5pbmdzICglKQprZXlfaW5kaWNhdG9ycyR3aXRoX2NhbmNlcl9zY3JlZW5pbmcgPC0gaGVhbHRoX2luZCRxLndpdGhfY2FuY2VyX3NjcmVlbmluZ19hZHVsdC4yMDE0IFttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGhlYWx0aF9pbmQkc3RhdGVfYWJiKV0KICAjIEFkdWx0cyB3aXRoIGFnZS1hcHByb3ByaWF0ZSB2YWNjaW5lcyAoJSkKa2V5X2luZGljYXRvcnMkd2l0aF92YWNjaW5lcyA8LSBoZWFsdGhfaW5kJHEud2l0aF92YWNjaW5lc19hZHVsdC4yMDE1IFttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGhlYWx0aF9pbmQkc3RhdGVfYWJiKV0KCiMgQWZmb3JkYWJpbGl0eSBhbmQgY29zdC1lZmZpY2llbmN5CiAgIyBJbmRpdmlkdWFscyB1bmRlciBhZ2UgNjUgd2l0aCBoaWdoIE9PUCBtZWRpY2FsIGNvc3RzIHJlbGF0aXZlIHRvIGFubnVhbCBob3VzZWhvbGQgaW5jb21lCmtleV9pbmRpY2F0b3JzJGhpZ2hfT09QX3JlbGF0aXZlIDwtIGhlYWx0aF9pbmQkYS5oaWdoX09PUF9yZWxhdGl2ZV91bmRlcjY1LjIwMTUgW21hdGNoKGtleV9pbmRpY2F0b3JzJHN0YXRlX2FiYiwgaGVhbHRoX2luZCRzdGF0ZV9hYmIpXQogICMgQXZlcmFnZSBhbm51YWwgZ3Jvd3RoIGluIGZhbWlseSBwcmVtaXVtcyBmb3IgZW1wbG95ZXIgY292ZXJhZ2UgKGJldHdlZW4gMjAxMCBhbmQgMjAxNSkKa2V5X2luZGljYXRvcnMkcHJlbWl1bV9hbm5fZ3Jvd3RoXzEwXzE1IDwtIGFjYV9nZW5lcmFsJHByZW1pdW1fZW1wX2F2Z19ncm93dGhfcGN0XzEwdG8xNVttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGFjYV9nZW5lcmFsJHN0YXRlX2FiYildCiAgIyBNYXJrZXRwbGFjZSBjb25zdW1lcnMgd2hvIGNvdWxkIHNlbGVjdCBhIHBsYW4gZm9yIGxlc3MgdGhhbiAkMTAwCmtleV9pbmRpY2F0b3JzJElNX3BsYW5fdW5kZXJfMTAwIDwtIGFjYV9nZW5lcmFsJGNvdl9ta3RfdW5kZXIxMDBEX3BjdFttYXRjaChrZXlfaW5kaWNhdG9ycyRzdGF0ZV9hYmIsIGFjYV9nZW5lcmFsJHN0YXRlX2FiYildCiAgIyBOZXQgaW5jcmVhc2UgaW4gZmVkZXJhbCBzcGVuZGluZyAobWlsbGlvbnMpCmtleV9pbmRpY2F0b3JzJGluY3JfZmVkX3NwZW5kaW5nX21pbCA8LSBhY2FfZ2VuZXJhbCRmZWRfc3BlbmRpbmdfbmV0X2luY3JfaW5NaWxbbWF0Y2goa2V5X2luZGljYXRvcnMkc3RhdGVfYWJiLCBhY2FfZ2VuZXJhbCRzdGF0ZV9hYmIpXQpgYGAKCiMgKDIpIEhlYWx0aCBPdXRjb21lcyBhbmQgQWNjZXNzCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBQTE9UIDUKcGxvdDUgPC0gKGdncGxvdChrZXlfaW5kaWNhdG9ycywgYWVzKGluc3VyZWRfcGN0XzIwMTQsIGRlYXRoc19hbWVuYWJsZV8yMDE0LCBjb2xvciA9IGluY29tZV9sZXZlbCwgc2hhcGUgPSBzdGF0ZV9oYXNfZXhwYW5kZWQpKQogICAgICAgICAgKyBnZW9tX3BvaW50KHNpemUgPSAyKQogICAgICAgICAgKyBnZW9tX3Ntb290aChhZXMoZ3JvdXAgPSBpbmNvbWVfbGV2ZWwpLCBtZXRob2QgPSAibG0iLCBsd2QgPSAxLCBzZSA9IEZBTFNFKQogICAgICAgICAgKyBsYWJzKHggPSAiJSBJbnN1cmVkIiwgeSA9ICJEZWF0aHMgUHJldmVudGFibGUgYnkgSGVhbHRoY2FyZSBJbnRlcnZlbnRpb24gXG4ocGVyIDEwMCwwMDAgUGVvcGxlKSIsIGNvbG9yID0gIkluY29tZSBcbkxldmVsIiwgc2hhcGUgPSAiU3RhdGUgaGFzIFxuRXhwYW5kZWQgXG5NZWRpY2FpZCIpCiAgICAgICAgICArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBicmV3ZXIucGFsKG4gPSA0LCBuYW1lID0gIkRhcmsyIikpCiAgICAgICAgICArIGdndGl0bGUoIlJlbGF0aW9uc2hpcCBCZXR3ZWVuIEF2b2lkYWJsZSBNb3J0YWxpdHkgYW5kIFxuSGVhbHRoIEluc3VyYW5jZSBDb3ZlcmFnZSBBbW9uZyBTdGF0ZXMiKQogICAgICAgICAgKyB0aGVtZV9taW5pbWFsKCkKICAgICAgICAgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIiwgaGp1c3QgPSAwLjUsIHNpemUgPSAxMikpKQpwbG90NQpgYGAKCgpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIyBEQVRBIFBST0NFU1NJTkcKCiMgT2J0YWluIHNoYXBlIGZpbGVzIG9mIFVTIHN0YXRlcwptYXBfc3RhdGVzID0gbWFwKCJzdGF0ZSIsIGZpbGwgPSBUUlVFLCBwbG90ID0gRkFMU0UpCgojIFN0YW5kYXJkaXplIG5hbWUgZm9ybWF0IHdpdGggcmVzdCBvZiBhc3NpZ25tZW50CiAgIyBGdW5jdGlvbiB0byBjb252ZXIgdG8gcHJvcGVyIGNhc2UKcHJvcGVyQ2FzZSA8LSBmdW5jdGlvbih4KSB7CiAgcyA8LSBzdHJzcGxpdCh4LCAiICIpW1sxXV0KICBwYXN0ZSh0b3VwcGVyKHN1YnN0cmluZyhzLCAxLDEpKSwgc3Vic3RyaW5nKHMsIDIpLAogICAgICBzZXA9IiIsIGNvbGxhcHNlPSIgIikKfQogICMgQ29udmVydCB0byBwcm9wZXIgY2FzZQptYXBfc3RhdGVzJHN0YXRlIDwtIHNhcHBseShtYXBfc3RhdGVzJG5hbWVzLCBwcm9wZXJDYXNlKQogICMgUmVuYW1lIHRoZSBtYWluIGNvbXBvbmVudCBvZiBzdGF0ZXMgd2l0aCBtdWx0aXBsZSBwYXJ0cyBpbiB0aGUgbWFwCm1hcF9zdGF0ZXMkc3RhdGVbbWFwX3N0YXRlcyRzdGF0ZSA9PSAiTWFzc2FjaHVzZXR0czptYWluIl0gPC0gIk1hc3NhY2h1c2V0dHMiCm1hcF9zdGF0ZXMkc3RhdGVbbWFwX3N0YXRlcyRzdGF0ZSA9PSAiTWljaGlnYW46c291dGgiXSA8LSAiTWljaGlnYW4iCm1hcF9zdGF0ZXMkc3RhdGVbbWFwX3N0YXRlcyRzdGF0ZSA9PSAiTmV3IFlvcms6bWFpbiJdIDwtICJOZXcgWW9yayIKbWFwX3N0YXRlcyRzdGF0ZVttYXBfc3RhdGVzJHN0YXRlID09ICJOb3J0aCBDYXJvbGluYTptYWluIl0gPC0gIk5vcnRoIENhcm9saW5hIgptYXBfc3RhdGVzJHN0YXRlW21hcF9zdGF0ZXMkc3RhdGUgPT0gIlZpcmdpbmlhOm1haW4iXSA8LSAiVmlyZ2luaWEiCm1hcF9zdGF0ZXMkc3RhdGVbbWFwX3N0YXRlcyRzdGF0ZSA9PSAiV2FzaGluZ3RvbjptYWluIl0gPC0gIldhc2hpbmd0b24iCiAgIyBNYXRjaCB3aXRoIHN0YXRlIGFiYnJldmlhdGlvbnMKbWFwX3N0YXRlcyRzdGF0ZV9hYmIgPC0gc3RhdGVfYWJiX2xvb2t1cCRzdGF0ZV9hYmJbbWF0Y2gobWFwX3N0YXRlcyRzdGF0ZSwgc3RhdGVfYWJiX2xvb2t1cCRzdGF0ZSldCiAgIyBUaGVuIHN0cmlwIG9mZiBhbGwgdGhlIGV4dHJhIGxvY2F0aW9uIGluZm9ybWF0aW9uIGZvciBzdGF0ZXMgd2l0aCBtdWx0aXBsZSBwYXJ0cyAobGVhdmluZyBqdXN0IHRoZSBzdGF0ZSBuYW1lKQpmb3IgKGkgaW4gMTpsZW5ndGgobWFwX3N0YXRlcyRzdGF0ZSkpIHsKICBtYXBfc3RhdGVzJHN0YXRlW2ldIDwtIHVubGlzdChzdHJzcGxpdChtYXBfc3RhdGVzJHN0YXRlW2ldLCAiOiIpKVsxXQp9CgojIEdldCBjb29yZGluYXRlcyBvZiBzdGF0ZSBjZW50ZXJzCnN0YXRlc19jZW50ZXJzIDwtIHN0YXRlLmNlbnRlcgpzdGF0ZS5jZW50ZXIgPC0gY2JpbmQoc3RhdGVzX2NlbnRlcnMsIHN0YXRlX2FiYl9sb29rdXApCgojIEhlYWx0aCBvdXRjb21lczogSW1wb3J0IGtleSBpbmRpY2F0b3JzIGRhdGEsIG1hdGNoZWQgYnkgc3RhdGUKICAgICMgUmVtZW1iZXIgdG8gbGF0ZXIgbWF0Y2ggaW5mb3JtYXRpb24gYmFzZWQgb24gc3RhdGUsIG5vdCBzdGF0ZSBhYmJyZXZpYXRpb24gKGR1ZSB0byBob3cgd2UgbGFiZWxsZWQgYWJvdmUpCm1hcF9zdGF0ZXMkZGVhdGhzX2FtZW5hYmxlXzIwMTQgPC0ga2V5X2luZGljYXRvcnMkZGVhdGhzX2FtZW5hYmxlXzIwMTRbbWF0Y2gobWFwX3N0YXRlcyRzdGF0ZSwga2V5X2luZGljYXRvcnMkc3RhdGUpXQptYXBfc3RhdGVzJHVzdWFsX2NhcmVfMjAxNSA8LSBrZXlfaW5kaWNhdG9ycyR1c3VhbF9jYXJlXzIwMTVbbWF0Y2gobWFwX3N0YXRlcyRzdGF0ZSwga2V5X2luZGljYXRvcnMkc3RhdGUpXQptYXBfc3RhdGVzJHdpdGhfY2FuY2VyX3NjcmVlbmluZyA8LSBrZXlfaW5kaWNhdG9ycyR3aXRoX2NhbmNlcl9zY3JlZW5pbmdbbWF0Y2gobWFwX3N0YXRlcyRzdGF0ZSwga2V5X2luZGljYXRvcnMkc3RhdGUpXQptYXBfc3RhdGVzJHdpdGhfdmFjY2luZXMgPC0ga2V5X2luZGljYXRvcnMkd2l0aF92YWNjaW5lc1ttYXRjaChtYXBfc3RhdGVzJHN0YXRlLCBrZXlfaW5kaWNhdG9ycyRzdGF0ZSldCgojIENvc3Qgb3V0Y29tZXM6IEltcG9ydCBrZXkgaW5kaWNhdG9ycyBkYXRhLCBtYXRjaGVkIGJ5IHN0YXRlCiAgICAjIFJlbWVtYmVyIHRvIGxhdGVyIG1hdGNoIGluZm9ybWF0aW9uIGJhc2VkIG9uIHN0YXRlLCBub3Qgc3RhdGUgYWJicmV2aWF0aW9uIChkdWUgdG8gaG93IHdlIGxhYmVsbGVkIGFib3ZlKQptYXBfc3RhdGVzJGhpZ2hfT09QX3JlbGF0aXZlIDwtIGtleV9pbmRpY2F0b3JzJGhpZ2hfT09QX3JlbGF0aXZlW21hdGNoKG1hcF9zdGF0ZXMkc3RhdGUsIGtleV9pbmRpY2F0b3JzJHN0YXRlKV0KbWFwX3N0YXRlcyRwcmVtaXVtX2Fubl9ncm93dGhfMTBfMTUgPC0ga2V5X2luZGljYXRvcnMkcHJlbWl1bV9hbm5fZ3Jvd3RoXzEwXzE1W21hdGNoKG1hcF9zdGF0ZXMkc3RhdGUsIGtleV9pbmRpY2F0b3JzJHN0YXRlKV0KbWFwX3N0YXRlcyRJTV9wbGFuX3VuZGVyXzEwMCA8LSBrZXlfaW5kaWNhdG9ycyRJTV9wbGFuX3VuZGVyXzEwMFttYXRjaChtYXBfc3RhdGVzJHN0YXRlLCBrZXlfaW5kaWNhdG9ycyRzdGF0ZSldCm1hcF9zdGF0ZXMkaW5jcl9mZWRfc3BlbmRpbmdfbWlsIDwtIGtleV9pbmRpY2F0b3JzJGluY3JfZmVkX3NwZW5kaW5nX21pbFttYXRjaChtYXBfc3RhdGVzJHN0YXRlLCBrZXlfaW5kaWNhdG9ycyRzdGF0ZSldCmBgYAoKCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgNjogTEVBRkxFVCBNQVAgLSBIRUFMVEggT1VUQ09NRVMKCihsZWFmbGV0KG1hcF9zdGF0ZXMpICU+JSAKICAgIHNldFZpZXcobGF0PTM5LjgyODIsIGxuZz0tOTYgLCB6b29tPTQpICU+JQogICAgYWRkUG9seWdvbnMoY29sb3IgPSAiIzMzMzMzMyIsIHdlaWdodCA9IDEsIHNtb290aEZhY3RvciA9IDAuNSwgZmlsbE9wYWNpdHkgPSAwKSAlPiUKICAgIGFkZFBvbHlnb25zKGdyb3VwID0gIlByZXZlbnRhYmxlIERlYXRocyIsIGZpbGxDb2xvciA9IH5jb2xvclF1YW50aWxlKCJSZFlsR24iLCAtZGVhdGhzX2FtZW5hYmxlXzIwMTQpKC1kZWF0aHNfYW1lbmFibGVfMjAxNCksIHNtb290aEZhY3RvciA9IDAuNSwgc3Ryb2tlID0gRkFMU0UsIGZpbGxPcGFjaXR5ID0gMC42LCBwb3B1cCA9IHBhc3RlKCI8Yj5TdGF0ZTogPC9iPiIsIG1hcF9zdGF0ZXMkc3RhdGUsICI8YnIvPiIsICI8Yj5QcmV2ZW50YWJsZSBNb3J0YWxpdHk8L2I+IiwgIjxici8+IiwgIjxiPnBlciAxMDAsMDAwOiA8L2I+IiwgbWFwX3N0YXRlcyRkZWF0aHNfYW1lbmFibGVfMjAxNCkpICU+JQogICAgYWRkUG9seWdvbnMoZ3JvdXAgPSAiQWNjZXNzIHRvIFVzdWFsIENhcmUiLCBmaWxsQ29sb3IgPSB+Y29sb3JRdWFudGlsZSgiUmRZbEduIiwgdXN1YWxfY2FyZV8yMDE1KSh1c3VhbF9jYXJlXzIwMTUpLCBzbW9vdGhGYWN0b3IgPSAwLjUsIHN0cm9rZSA9IEZBTFNFLCBmaWxsT3BhY2l0eSA9IDAuNiwgcG9wdXAgPSBwYXN0ZSgiPGI+U3RhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHN0YXRlLCAiPGJyLz4iLCAiPGI+QWNjZXNzIHRvIFVzdWFsPC9iPiIsICI8YnIvPiIsICI8Yj5Tb3VyY2Ugb2YgQ2FyZTogPC9iPiIsIG1hcF9zdGF0ZXMkdXN1YWxfY2FyZV8yMDE1LCAiJSIpKSAlPiUKICAgIGFkZFBvbHlnb25zKGdyb3VwID0gIkNhbmNlciBTY3JlZW5pbmdzIFJhdGUiLCBmaWxsQ29sb3IgPSB+Y29sb3JRdWFudGlsZSgiUmRZbEduIiwgd2l0aF9jYW5jZXJfc2NyZWVuaW5nKSh3aXRoX2NhbmNlcl9zY3JlZW5pbmcpLCBzbW9vdGhGYWN0b3IgPSAwLjUsIHN0cm9rZSA9IEZBTFNFLCBmaWxsT3BhY2l0eSA9IDAuNiwgcG9wdXAgPSBwYXN0ZSgiPGI+U3RhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHN0YXRlLCAiPGJyLz4iLCAiPGI+Q2FuY2VyIFNjcmVlbmluZ3M8L2I+IiwgIjxici8+IiwgIjxiPlJhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHdpdGhfY2FuY2VyX3NjcmVlbmluZywgIiUiKSkgJT4lCiAgICBhZGRQb2x5Z29ucyhncm91cCA9ICJBZHVsdCBWYWNjaW5hdGlvbiBSYXRlIiwgZmlsbENvbG9yID0gfmNvbG9yUXVhbnRpbGUoIlJkWWxHbiIsIHdpdGhfdmFjY2luZXMpKHdpdGhfdmFjY2luZXMpLCBzbW9vdGhGYWN0b3IgPSAwLjUsIHN0cm9rZSA9IEZBTFNFLCBmaWxsT3BhY2l0eSA9IDAuNiwgcG9wdXAgPSBwYXN0ZSgiPGI+U3RhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHN0YXRlLCAiPGJyLz4iLCAiPGI+VmFjY2luYXRpb248L2I+IiwgIjxici8+IiwgIjxiPlJhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHdpdGhfdmFjY2luZXMsICIlIikpICU+JQogICAgYWRkTGFiZWxPbmx5TWFya2VycyhkYXRhID0gZmlsdGVyKHN0YXRlLmNlbnRlciwgc3RhdGVfYWJiIT0iQUsiICYgc3RhdGVfYWJiIT0iSEkiKSwgbG5nID0gfngsIGxhdCA9IH55LCBsYWJlbCA9IH5zdGF0ZV9hYmIsIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBULCBkaXJlY3Rpb24gPSAndG9wJywgdGV4dE9ubHkgPSBUKSkgJT4lCiAgICBhZGRMYXllcnNDb250cm9sKAogICAgICBiYXNlR3JvdXBzID0gYygiUHJldmVudGFibGUgRGVhdGhzIiwgIkFjY2VzcyB0byBVc3VhbCBDYXJlIiwgIkNhbmNlciBTY3JlZW5pbmdzIFJhdGUiLCAiQWR1bHQgVmFjY2luYXRpb24gUmF0ZSIpLAogICAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpKSkgCmBgYAoKCiMgKDMpIEFmZm9yZGFiaWxpdHkgYW5kIENvc3QgT3V0Y29tZXMKCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgNzogTEVBRkxFVCBNQVAgLSBBRkZPUkRBQklMSVRZIC8gQ09TVCBPVVRDT01FUwoKKGxlYWZsZXQobWFwX3N0YXRlcykgJT4lIAogICAgc2V0VmlldyhsYXQ9MzkuODI4MiwgbG5nPS05NiAsIHpvb209NCkgJT4lCiAgICBhZGRQb2x5Z29ucyhjb2xvciA9ICIjMzMzMzMzIiwgd2VpZ2h0ID0gMSwgc21vb3RoRmFjdG9yID0gMC41LCBmaWxsT3BhY2l0eSA9IDApICU+JQogICAgYWRkUG9seWdvbnMoZ3JvdXAgPSAiQ29udGFpbmVkIE9PUCBDb3N0cyIsIGZpbGxDb2xvciA9IH5jb2xvclF1YW50aWxlKCJSZFlsR24iLCAtaGlnaF9PT1BfcmVsYXRpdmUpKC1oaWdoX09PUF9yZWxhdGl2ZSksIHNtb290aEZhY3RvciA9IDAuNSwgc3Ryb2tlID0gRkFMU0UsIGZpbGxPcGFjaXR5ID0gMC42LCBwb3B1cCA9IHBhc3RlKCI8Yj5TdGF0ZTogPC9iPiIsIG1hcF9zdGF0ZXMkc3RhdGUsICI8YnIvPiIsICI8Yj5IaWdoIE9PUCBSZWxhdGl2ZTwvYj4iLCAiPGJyLz4iLCAiPGI+dG8gSW5jb21lOiA8L2I+IiwgbWFwX3N0YXRlcyRoaWdoX09PUF9yZWxhdGl2ZSwgIiUiKSkgJT4lCiAgICBhZGRQb2x5Z29ucyhncm91cCA9ICJQcmVtaXVtIEdyb3d0aCBSYXRlIiwgZmlsbENvbG9yID0gfmNvbG9yUXVhbnRpbGUoIlJkWWxHbiIsIC1wcmVtaXVtX2Fubl9ncm93dGhfMTBfMTUpKC1wcmVtaXVtX2Fubl9ncm93dGhfMTBfMTUpLCBzbW9vdGhGYWN0b3IgPSAwLjUsIHN0cm9rZSA9IEZBTFNFLCBmaWxsT3BhY2l0eSA9IDAuNiwgcG9wdXAgPSBwYXN0ZSgiPGI+U3RhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHN0YXRlLCAiPGJyLz4iLCAiPGI+QW5udWFsIFByZW1pdW08L2I+IiwgIjxici8+IiwgIjxiPkdyb3d0aCBSYXRlOiA8L2I+IiwgbWFwX3N0YXRlcyRwcmVtaXVtX2Fubl9ncm93dGhfMTBfMTUsICIlIikpICU+JQogICAgYWRkUG9seWdvbnMoZ3JvdXAgPSAiQWZmb3JkYWJsZSBJbmRpdmlkdWFsIE1hcmtldHBsYWNlIFBsYW4iLCBmaWxsQ29sb3IgPSB+Y29sb3JRdWFudGlsZSgiUmRZbEduIiwgSU1fcGxhbl91bmRlcl8xMDApKElNX3BsYW5fdW5kZXJfMTAwKSwgc21vb3RoRmFjdG9yID0gMC41LCBzdHJva2UgPSBGQUxTRSwgZmlsbE9wYWNpdHkgPSAwLjYsIHBvcHVwID0gcGFzdGUoIjxiPlN0YXRlOiA8L2I+IiwgbWFwX3N0YXRlcyRzdGF0ZSwgIjxici8+IiwgIjxiPk1hcmtldHBsYWNlIENvbnN1bWVyczwvYj4iLCAiPGJyLz4iLCAiPGI+V2hvIENhbiBTZWxlY3QgUGxhbjwvYj4iLCAiPGJyLz4iLCI8Yj5VbmRlciAkMTAwOiA8L2I+IiwgbWFwX3N0YXRlcyRJTV9wbGFuX3VuZGVyXzEwMCAqIDEwMCwgIiUiKSkgJT4lCiAgICBhZGRQb2x5Z29ucyhncm91cCA9ICJJbmNyZWFzZSBpbiBGZWRlcmFsIFNwZW5kaW5nIiwgZmlsbENvbG9yID0gfmNvbG9yUXVhbnRpbGUoIlJkWWxHbiIsIC1pbmNyX2ZlZF9zcGVuZGluZ19taWwpKC1pbmNyX2ZlZF9zcGVuZGluZ19taWwpLCBzbW9vdGhGYWN0b3IgPSAwLjUsIHN0cm9rZSA9IEZBTFNFLCBmaWxsT3BhY2l0eSA9IDAuNiwgcG9wdXAgPSBwYXN0ZSgiPGI+U3RhdGU6IDwvYj4iLCBtYXBfc3RhdGVzJHN0YXRlLCAiPGJyLz4iLCAiPGI+TmV0IEluY3JlYXNlIGluIEZlZGVyYWw8L2I+IiwgIjxici8+IiwgIjxiPlNwZW5kaW5nPC9iPjogJCIsIG1hcF9zdGF0ZXMkaW5jcl9mZWRfc3BlbmRpbmdfbWlsLCAibWlsbGlvbiIpKSAlPiUKICAgIGFkZExhYmVsT25seU1hcmtlcnMoZGF0YSA9IGZpbHRlcihzdGF0ZS5jZW50ZXIsIHN0YXRlX2FiYiE9IkFLIiAmIHN0YXRlX2FiYiE9IkhJIiksIGxuZyA9IH54LCBsYXQgPSB+eSwgbGFiZWwgPSB+c3RhdGVfYWJiLCBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gVCwgZGlyZWN0aW9uID0gJ3RvcCcsIHRleHRPbmx5ID0gVCkpICU+JQogICAgYWRkTGF5ZXJzQ29udHJvbCgKICAgICAgYmFzZUdyb3VwcyA9IGMoIkNvbnRhaW5lZCBPT1AgQ29zdHMiLCAiUHJlbWl1bSBHcm93dGggUmF0ZSIsICJBZmZvcmRhYmxlIEluZGl2aWR1YWwgTWFya2V0cGxhY2UgUGxhbiIsICJJbmNyZWFzZSBpbiBGZWRlcmFsIFNwZW5kaW5nIiksCiAgICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkpKSAKYGBgCgoKIyAoNCkgU3VtbWFyeSBvZiBTdGF0ZXMnIFBlcmZvcm1hbmNlCgpgYGB7cn0KIyBDcmVhdGUgZGF0YSB0YWJsZSByZXBvcnRpbmcgdmFsdWVzCmRhdGFfdGFibGVfdmFsdWVzIDwtIGtleV9pbmRpY2F0b3JzWyAsIGMoInN0YXRlIiwgImluc3VyZWRfcGN0XzIwMTUiLCAiZGVhdGhzX2FtZW5hYmxlXzIwMTQiLCAidXN1YWxfY2FyZV8yMDE1IiwgImhpZ2hfT09QX3JlbGF0aXZlIiwgInByZW1pdW1fYW5uX2dyb3d0aF8xMF8xNSIpXQoKIyBDcmVhdGUgZGF0YSB0YWJsZSByZXBvcnRpbmcgcmFuawpkYXRhX3RhYmxlX3JhbmsgPC0gZGF0YV90YWJsZV92YWx1ZXMKCiMgQ29udmVydCBlYWNoIGZ1bmN0aW9uIHRvIHJhbmsKICAjIFJhbmsgMSBpcyBhbHdheXMgbW9yZSBmYXZvcmFibGUgKHJlZ2FyZGxlc3Mgb2YgZGVmaW5pdGlvbiBvZiB2YXJpYWJsZSkgICAgCmRhdGFfdGFibGVfcmFuayRyX2luc3VyZWRfcGN0XzIwMTUgPC0gcmFuaygtZGF0YV90YWJsZV92YWx1ZXMkaW5zdXJlZF9wY3RfMjAxNSwgbmEubGFzdCA9ICJrZWVwIiwgdGllcy5tZXRob2QgPSAibWluIikKZGF0YV90YWJsZV9yYW5rJHJfZGVhdGhzX2FtZW5hYmxlXzIwMTQgPC0gcmFuayhkYXRhX3RhYmxlX3ZhbHVlcyRkZWF0aHNfYW1lbmFibGVfMjAxNCwgbmEubGFzdCA9ICJrZWVwIiwgdGllcy5tZXRob2QgPSAibWluIikKZGF0YV90YWJsZV9yYW5rJHJfdXN1YWxfY2FyZV8yMDE1IDwtIHJhbmsoLWRhdGFfdGFibGVfdmFsdWVzJHVzdWFsX2NhcmVfMjAxNSwgbmEubGFzdCA9ICJrZWVwIiwgdGllcy5tZXRob2QgPSAibWluIikKZGF0YV90YWJsZV9yYW5rJHJfaGlnaF9PT1BfcmVsYXRpdmUgPC0gcmFuayhkYXRhX3RhYmxlX3ZhbHVlcyRoaWdoX09PUF9yZWxhdGl2ZSwgbmEubGFzdCA9ICJrZWVwIiwgdGllcy5tZXRob2QgPSAibWluIikKZGF0YV90YWJsZV9yYW5rJHJfcHJlbWl1bV9hbm5fZ3Jvd3RoXzEwXzE1IDwtIHJhbmsoZGF0YV90YWJsZV92YWx1ZXMkcHJlbWl1bV9hbm5fZ3Jvd3RoXzEwXzE1LCBuYS5sYXN0ID0gImtlZXAiLCB0aWVzLm1ldGhvZCA9ICJtaW4iKQogICMgUmVtb3ZlIHZhbHVlIHZhcmlhYmxlcwpkYXRhX3RhYmxlX3JhbmskaW5zdXJlZF9wY3RfMjAxNSA8LSBOVUxMCmRhdGFfdGFibGVfcmFuayRkZWF0aHNfYW1lbmFibGVfMjAxNCA8LSBOVUxMCmRhdGFfdGFibGVfcmFuayR1c3VhbF9jYXJlXzIwMTUgPC0gTlVMTApkYXRhX3RhYmxlX3JhbmskaGlnaF9PT1BfcmVsYXRpdmUgPC0gTlVMTApkYXRhX3RhYmxlX3JhbmskcHJlbWl1bV9hbm5fZ3Jvd3RoXzEwXzE1IDwtIE5VTEwKYGBgCgpUaGUgZm9sbG93aW5nIGRhdGEgdGFibGUgcHJlc2VudHMgdGhlIHJhbmtpbmdzIG9mIHRoZSBzdGF0ZXMgb24gdGhlIGZvbGxvd2luZyBpbnN1cmFuY2UgY292ZXJhZ2UsIGhlYWx0aCBhbmQgYWZmb3JkYWJpbGl0eSBvdXRjb21lczoKMSkgUGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIGluc3VyZWQKMikgRGVhdGhzIHByZXZlbnRhYmxlIGJ5IGhlYWx0aGNhcmUgaW50ZXJ2ZW50aW9uIChwZXIgMTAwLDAwMCBwZW9wbGUpCjMpIFByb3BvcnRpb24gb2YgYWR1bHRzIHdpdGggYWNjZXNzIHRvIGEgdXN1YWwgc291cmNlIG9mIGNhcmUKNCkgUHJvcG9ydGlvbiBvZiBwZW9wbGUgd2l0aCBoaWdoIG91dC1vZi1wb2NrZXQgY29zdHMgKHJlbGF0aXZlIHRvIGhvdXNlaG9sZCBpbmNvbWUpCjUpIEFubnVhbCByYXRlIG9mIGhlYWx0aCBpbnN1cmFuY2UgcHJlbWl1bSBncm93dGggZnJvbSAyMDEwIHRvIDIwMTUKQSByYW5rIG9mIDEgYWx3YXlzIGluZGljYXRlcyB0aGUgbW9yZSBmYXZvcmFibGUgb3V0Y29tZSAoaS5lLiBoaWdoZXIgaW5zdXJhbmNlIGFuZCB0cmVhdG1lbnQgYWNjZXNzIHJhdGUsIGxvd2VyIHByZXZlbnRhYmxlIG1vcnRhbGl0eSwgT09QIGNvc3RzIGFuZCBwcmVtaXVtIGdyb3d0aCkKCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CiMjIFBMT1QgODogREFUQSBUQUJMRSBSQU5LSU5HIFRIRSBTVEFURVMgT04gVkFSSU9VUyBNRUFTVVJFUwpkYXRhdGFibGUoZGF0YV90YWJsZV9yYW5rLCByb3duYW1lcyA9IEZBTFNFLCBjb2xuYW1lcyA9IGMoIlN0YXRlIiwgIlBlcmNlbnRhZ2UgSW5zdXJlZCIsICJGZXdlciBQcmV2ZW50YWJsZSBEZWF0aHMiLCAiVXN1YWwgQ2FyZSBBY2Nlc3MiLCAiT09QIENvbnRhaW5lZCIsICJMb3dlciBBbm51YWwgUHJlbWl1bSBHcm93dGgiKSwgY2FwdGlvbiA9ICJSYW5rIG9mIHRoZSA1MCBTdGF0ZXMgaW4gSW5zdXJhbmNlIENvdmVyYWdlIGFuZCBIZWFsdGggT3V0Y29tZXMiKQpgYGAKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgoKCmBgYHtyfQpsaWJyYXJ5KHRtKQpsaWJyYXJ5KHRtLnBsdWdpbi5sZXhpc25leGlzKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShndG9vbHMpICAjIGZvciBzbWFydGJpbmQKbGlicmFyeShkcGx5cikgICAjIGZvciBkYXRhX2ZyYW1lCmxpYnJhcnkobHVicmlkYXRlKSAgICMgZm9yIGRhdGUgZm9ybWF0dGluZwpsaWJyYXJ5KHN0cmluZ3IpICAKbGlicmFyeSh0b29scykgICMgVGl0bGUgY2FzZQpsaWJyYXJ5KHF1YW50ZWRhKQpsaWJyYXJ5KGdncGxvdDIpCgojIENvbWJpbmUgQ1NWIGFuZCBIVE1MIEZpbGVzCmRhdGEgPC0gcmVhZF9leGNlbCgiTGV4aXNOZXhpcy9OWVRpbWVzX01ldGFkYXRhLnhsc3giKQpjb2xuYW1lcyhkYXRhKSA8LSB0b2xvd2VyKGNvbG5hbWVzKGRhdGEpKQoKIyBDb3JyZWN0IGRhdGEKZGF0YSRkYXRlIDwtIHN1YnN0cihwYXJzZV9kYXRlX3RpbWUoZGF0YSRkYXRlLCBjKCJtZHkiKSksMSwxMCkKZGF0YSRhdXRob3IgPC0gdG9UaXRsZUNhc2UodG9sb3dlcihkYXRhJGJ5bGluZSkpCmRhdGEkYnlsaW5lIDwtIE5VTEwKCiMjIEdldCBUZXh0IGZpbGVzCnNvdXJjZTEgPC0gTGV4aXNOZXhpc1NvdXJjZSgiTGV4aXNOZXhpcy9UaGVfTmV3X1lvcmsxLmh0bWwiKQpzb3VyY2UyIDwtIExleGlzTmV4aXNTb3VyY2UoIkxleGlzTmV4aXMvVGhlX05ld19Zb3JrMi5odG1sIikKCmNvcnB1czEgPC0gQ29ycHVzKHNvdXJjZTEsIHJlYWRlckNvbnRyb2wgPSBsaXN0KGxhbmd1YWdlID0gTkEpKQpjb3JwdXMyIDwtIENvcnB1cyhzb3VyY2UyLCByZWFkZXJDb250cm9sID0gbGlzdChsYW5ndWFnZSA9IE5BKSkKCmNvcnB1cyA8LSBjKGNvcnB1czEsIGNvcnB1czIpCgojIENvbnZlcnQgdG8gcXVhbnRlZGEgY29ycHVzCmNvcnB1cyA8LSBxdWFudGVkYTo6Y29ycHVzKGNvcnB1cykKCiMjIEFkZCBNZXRhZGF0YQojIENoZWNrOiBtYXRjaChkYXRhJGhlYWRsaW5lLCBjb3JwdXMkZG9jdW1lbnRzJGhlYWRpbmcpCmNvcnB1cyRkb2N1bWVudHMkZGF0ZXRpbWVzdGFtcCA8LSBzdWJzdHJpbmcoY29ycHVzJGRvY3VtZW50cyRkYXRldGltZXN0YW1wLCAxLDQpCmNvcnB1cyRkb2N1bWVudHMkZGF0ZSA8LSBjb3JwdXMkZG9jdW1lbnRzJGRhdGV0aW1lc3RhbXAKY29ycHVzJGRvY3VtZW50cyRkZXNjcmlwdGlvbiA8LSBjb3JwdXMkZG9jdW1lbnRzJGlkCgojIG9wdGlvbnMod2lkdGggPSAyMDApCiMga3dpYyhjb3JwdXMsICJUcnVtcCIpCiMgCnNhdmUoY29ycHVzLCBmaWxlPSJueXRpbWVzLnJkYSIpCmBgYAojIHRoZSBOdW1tYmVyIG9mIGFydGljbGVzIG1lbnRpb25zIEFmZm9yZGFibGUgY2FyZSBieSB5ZWFycwoKYGBge3J9CmRhdCA8LSBkYXRhLmZyYW1lKGRhdGUgPWNvcnB1cyRkb2N1bWVudHMkZGF0ZXRpbWVzdGFtcCwgbGV2ZWxzPWMoMToxMDAwKSkKZ2dwbG90KGRhdGE9ZGF0LCBhZXMoeD1kYXRlKSkrZ2VvbV9iYXIoc3RhdD0iY291bnQiKStnZ3RpdGxlKCJOdW1iZXIgb2YgYXJ0aWNsZXMgbWVudGlvbmVkIEFDQSBieSB5ZWFycyIpK3RoZW1lX3R1ZnRlKCkreWxhYigiTnVtYmVyIG9mIGFydGljbGVzIikgKyB4bGFiKCJ5ZWFyIikKCmBgYAoKYGBge3J9CmxvYWQoIm55dGltZXMucmRhIikKZGZtdG90YWwgPC0gZGZtKGNvcnB1cywgcmVtb3ZlID0gc3RvcHdvcmRzKCJlbmdsaXNoIiksIHN0ZW0gPSBUUlVFLCByZW1vdmVQdW5jdCA9IFRSVUUsIHJlbW92ZU51bWJlcnMgPSBUUlVFLCB0b2xvd2VyID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUpCmRmbXRvdGFsWywgMTo1XQpoZWFkKHN0b3B3b3JkcygiZW5nbGlzaCIpLCAyMCkKZnJlcTwtdG9wZmVhdHVyZXMoZGZtdG90YWwsIDIwKQpsaWJyYXJ5KGdncGxvdDIpICAKd2YgPC0gZGF0YS5mcmFtZSh3b3JkPW5hbWVzKGZyZXEpLCBmcmVxPWZyZXEpICAgCnAgPC0gZ2dwbG90KHN1YnNldCh3ZiwgZnJlcT41MCksIGFlcyh3b3JkLCBmcmVxKSkgICAgCnAgPC0gcCArIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKcCA8LSBwICsgZ2VvbV90ZXh0KGFlcyhsYWJlbD1mcmVxKSwgdmp1c3Q9LTAuMikrIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPSB3ZiR3b3JkKSAgIApwIDwtIHAgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKStnZ3RpdGxlKCJXb3JkIGZyZXF1ZW5jeSBmcm9tIDIwMTEtMjAxNyIpK3RoZW1lX3R1ZnRlKCkreWxhYigiRnJlcXVlbmN5IG9mIFN0ZW0iKSArIHhsYWIoIlRvcCAzMCBVc2VkIFN0ZW0iKQpwCmBgYAoKYGBge3J9CmxpYnJhcnkocXVhbnRlZGEpCmxpYnJhcnkoc3RyaW5ncikKbG9hZCgnbnl0aW1lcy5yZGEnKQpsaWJyYXJ5KHRtKQpOWVRfc291cmNlIDwtIFZlY3RvclNvdXJjZShjb3JwdXMkZG9jdW1lbnRzWywxXSkKTllUIDwtIFZDb3JwdXMoTllUX3NvdXJjZSkKZG9jdW1lbnRzIDwtIGNvcnB1cyRkb2N1bWVudHMKbGlicmFyeShxZGFwKQpyZW1vdmVOdW1QdW5jdCA8LSBmdW5jdGlvbih4KXtnc3ViKCJbXls6YWxwaGE6XVs6c3BhY2U6XV0qIiwgIiIsIHgpfQpjbGVhbl9jb3JwdXMgPC0gZnVuY3Rpb24oY29ycHVzKXsKY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIGNvbnRlbnRfdHJhbnNmb3JtZXIocmVwbGFjZV9zeW1ib2wpKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlV29yZHMsIGMoc3RvcHdvcmRzKCJlbiIpLCAid2lsbCIsICJjYW4iLCAiUGF1bApLcnVnbWFuIiwgIkRhdmlkIEJyb29rcyIsICJUaG9tYXMgTC4gRnJpZWRtYW4iLCAiTWF1cmVlbiBEb3dkIiwgIk5pY2hvbGFzCktyaXN0b2YiKSkKIyBXZSBjb3VsZCBhZGQgbW9yZSBzdG9wIHdvcmRzIGFzIGFib3ZlCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBzdHJpcFdoaXRlc3BhY2UpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCByZW1vdmVOdW1iZXJzKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgY29udGVudF90cmFuc2Zvcm1lcihyZW1vdmVOdW1QdW5jdCkpCnJldHVybihjb3JwdXMpCn0KbGlicmFyeShTbm93YmFsbEMpCk5ZVF9jbGVhbiA8LSBjbGVhbl9jb3JwdXMoTllUKQpOWVRfc3RlbSA8LSB0bV9tYXAoTllUX2NsZWFuLCBzdGVtRG9jdW1lbnQpCm1ldGEoTllUX3N0ZW0sIHR5cGUgPSAibG9jYWwiLCB0YWcgPSAiYXV0aG9yIikgPC0gZG9jdW1lbnRzJGF1dGhvcgpOWVRfZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChOWVRfc3RlbSkKTllUX3RkbSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoTllUX3N0ZW0pCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXRleHQpCk5ZVF90ZG0yIDwtIHRpZHkoTllUX3RkbSkKTllUX2R0bTIgPC0gdGlkeShOWVRfZHRtKQpOWVRfdGlkeSA8LSB0aWR5KE5ZVF9zdGVtKQpOWVRfdGRtMiA8LSBtZXJnZShOWVRfdGRtMiwgTllUX3RpZHksIGJ5LnggPSAiZG9jdW1lbnQiLCBieS55ID0gImlkIiwgYWxsLnggPQpUUlVFKQpOWVRfZHRtMiA8LSBtZXJnZShOWVRfZHRtMiwgTllUX3RpZHksIGJ5LnggPSAiZG9jdW1lbnQiLCBieS55ID0gImlkIiwgYWxsLnggPQpUUlVFKQoKYGBgCgpgYGB7cn0KbGlicmFyeSh3b3JkY2xvdWQpCmF0eHQgPC0gZG9jdW1lbnRzJHRleHRzW2RvY3VtZW50cyRkYXRldGltZXN0YW1wID09ICIyMDExIl0KYnR4dCA8LSBkb2N1bWVudHMkdGV4dHNbZG9jdW1lbnRzJGRhdGV0aW1lc3RhbXAgPT0gIjIwMTIiXQpjdHh0IDwtIGRvY3VtZW50cyR0ZXh0c1tkb2N1bWVudHMkZGF0ZXRpbWVzdGFtcCA9PSAiMjAxMyJdCmR0eHQgPC0gZG9jdW1lbnRzJHRleHRzW2RvY3VtZW50cyRkYXRldGltZXN0YW1wID09ICIyMDE0Il0KZXR4dCA8LSBkb2N1bWVudHMkdGV4dHNbZG9jdW1lbnRzJGRhdGV0aW1lc3RhbXAgPT0gIjIwMTUiXQpmdHh0IDwtIGRvY3VtZW50cyR0ZXh0c1tkb2N1bWVudHMkZGF0ZXRpbWVzdGFtcCA9PSAiMjAxNiJdCmd0eHQgPC0gZG9jdW1lbnRzJHRleHRzW2RvY3VtZW50cyRkYXRldGltZXN0YW1wID09ICIyMDE3Il0KCmNsZWFuLnRleHQgPC0gZnVuY3Rpb24oeCkKewojIHRvbG93ZXIKeCA9IHRvbG93ZXIoeCkKIyByZW1vdmUgcnQKeCA9IGdzdWIoInJ0IiwgIiIsIHgpCiMgcmVtb3ZlIGF0CnggPSBnc3ViKCJAXFx3KyIsICIiLCB4KQojIHJlbW92ZSBwdW5jdHVhdGlvbgp4ID0gZ3N1YigiW1s6cHVuY3Q6XV0iLCAiIiwgeCkKIyByZW1vdmUgbnVtYmVycwp4ID0gZ3N1YigiW1s6ZGlnaXQ6XV0iLCAiIiwgeCkKIyByZW1vdmUgbGlua3MgaHR0cAp4ID0gZ3N1YigiaHR0cFxcdysiLCAiIiwgeCkKIyByZW1vdmUgdGFicwp4ID0gZ3N1YigiWyB8XHRdezIsfSIsICIiLCB4KQojIHJlbW92ZSBibGFuayBzcGFjZXMgYXQgdGhlIGJlZ2lubmluZwp4ID0gZ3N1YigiXiAiLCAiIiwgeCkKIyByZW1vdmUgYmxhbmsgc3BhY2VzIGF0IHRoZSBlbmQKeCA9IGdzdWIoIiAkIiwgIiIsIHgpCnJldHVybih4KQp9CgphY2xlYW4gPC0gY2xlYW4udGV4dChhdHh0KQpiY2xlYW4gPC0gY2xlYW4udGV4dChidHh0KQpjY2xlYW4gPC0gY2xlYW4udGV4dChjdHh0KQpkY2xlYW4gPC0gY2xlYW4udGV4dChkdHh0KQplY2xlYW4gPC0gY2xlYW4udGV4dChldHh0KQpmY2xlYW4gPC0gY2xlYW4udGV4dChmdHh0KQpnY2xlYW4gPC0gY2xlYW4udGV4dChndHh0KQoKYSA8LSBwYXN0ZShhY2xlYW4sIGNvbGxhcHNlPSIgIikKYiA8LSBwYXN0ZShiY2xlYW4sIGNvbGxhcHNlPSIgIikKYyA8LSBwYXN0ZShjY2xlYW4sIGNvbGxhcHNlPSIgIikKZCA8LSBwYXN0ZShkY2xlYW4sIGNvbGxhcHNlPSIgIikKZSA8LSBwYXN0ZShlY2xlYW4sIGNvbGxhcHNlPSIgIikKZiA8LSBwYXN0ZShmY2xlYW4sIGNvbGxhcHNlPSIgIikKZyA8LSBwYXN0ZShnY2xlYW4sIGNvbGxhcHNlPSIgIikKCiMgcHV0IGV2ZXJ5dGhpbmcgaW4gYSBzaW5nbGUgdmVjdG9yCmFsbCA8LSBjKGEsYixjLGQsZSxmLGcpCmFsbCA8LSByZW1vdmVXb3JkcyhhbGwsIGMoIndpbGwiLCAiY2FuIiwgInRoZSIsICJ0aGF0IiwiYXJlIikpCiMgY3JlYXRlIGNvcnB1cwpjb3JwdXMyIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UoYWxsKSkKIyBjcmVhdGUgdGVybS1kb2N1bWVudCBtYXRyaXgKY2xvdWR0ZG0gPC0gVGVybURvY3VtZW50TWF0cml4KGNvcnB1czIpCiMgY29udmVydCBhcyBtYXRyaXgKY2xvdWR0ZG0gPC0gYXMubWF0cml4KGNsb3VkdGRtKQojIGFkZCBjb2x1bW4gbmFtZXMKY29sbmFtZXMoY2xvdWR0ZG0pIDwtIGMoIjIwMTEiLCIyMDEyIiwiMjAxMyIsIjIwMTQiLCIyMDE1IiwiMjAxNiIsIjIwMTciKQpjb21wYXJpc29uLmNsb3VkKGNsb3VkdGRtLCByYW5kb20ub3JkZXI9RkFMU0UsY29sb3JzID0gYnJld2VyLnBhbCg4LCAiRGFyazIiKSx0aXRsZS5zaXplPTEuNSwgbWF4LndvcmRzID0gMjAwKQpgYGAKCg==